[分类] Jzoj P1320 拯救奶牛

Description

  贝希被困在一个三角形的迷宫之中。这个迷宫有N行(1 <= N <= 1000000)。比如下图是一个3行的迷宫。
  
  迷宫的第i行有2*i-1个三角形,从左到右分别编号为(i,1)、(i,2)等等。贝希每次可以从一个三角形走到任意一个一个跟当前的三角形有邻边的三角形。比如说,如果她目前处于三角形(3,3),那么,她可以走到三角形(3,2)、(3,4)和(4,4)。贝希每次需要一分钟的时间来移动到下一个三角形。
  
  农夫约翰发现贝希被困了!于是她跟踪贝希的iPhone手机(可怜的触摸屏~),得知贝希目前处于三角形(Si,Sj)。因为约翰对贝希有着无穷无尽的浓浓爱意,所以他希望贝希能尽可能快地回到他的身边。
  在迷宫的三角形之中,有M(1 <= M <= 10000)个是出口。在任何一个出口都可以让贝希逃离迷宫。一旦贝希进入一个作为出口的三角形,她用多一分钟就可以逃离这个迷宫。
  找到一个可以让贝希逃离迷宫最小时间T,并输出她应该从哪一个出口逃离迷宫,这个出口记为(OUTi,OUTj)。如果有多个出口同时需要时间T,输出那个行的编号小的出口,如果仍然有多个出口,输出那个列的编号小的。
 

Input

  第一行:两个由空格隔开的整数:N和M。
  第二行:两个由空格隔开的整数:Si和Sj。
  第三到第M+2行:第i+2行有两个由空格隔开的整数Ei和Ej,表示三角形(Ei,Ej)是出口。

Output

  第一行:两个由空格隔开的整数:OUTi和OUTj。
  第二行:一个单独的整数:T。
 

Sample Input

4 2
2 1
3 5
4 4

Sample Output

4 4
4

 

题解

  • 把原三角形旋转一下,看成三个三角形,顶部分别是原三角形最上、最左下和最右下的三个小三角
  • 于原三角形的侧着走,相当于在另两个三角形中的横着走,那么记录一个点分别在三个三角形中的行数,最小步数即为三个绝对值的和

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 int n,m,ans,r;
 8 struct node {int x,y;}p,q,mn;
 9 int work(node p,node q)
10 {
11     int l,r,sum=0,x=abs(p.x-q.x); 
12     if (!x) return abs(p.y-q.y);
13     sum+=x*2-(q.y&1);
14     if (q.y&1) l=q.y+1,r=l+(x-1)*2; else l=q.y,r=l+x*2;
15     if (l<=p.y&&p.y<=r) sum+=(p.y&1);
16     else 
17     {
18         if (abs(p.y-l)<abs(p.y-r)) sum+=abs(p.y-l); else sum+=abs(p.y-r);
19     }
20     return sum;
21 }
22 int main()
23 {
24     scanf("%d%d%d%d",&n,&m,&p.x,&p.y),ans=0x7fffffff;
25     for (int i=1;i<=m;i++)
26     {
27         scanf("%d%d",&q.x,&q.y);
28         if (!(q.y<=q.x*2-1&&1<=q.x&&q.x<=n)) continue;
29         if (q.x>p.x) r=work(q,p); else r=work(p,q);
30         if (r+1<ans) ans=r+1,mn=q;
31     }
32     printf("%d %d\n%d",mn.x,mn.y,ans);
33 }

 

posted @ 2019-03-04 20:47  BEYang_Z  阅读(294)  评论(0编辑  收藏  举报