N∗M 的棋盘上有一个受伤的国王与一个要去救援国王的骑士,他们每个单位时间必须同时移动一次寻找对方。如下图所示,黑色的图例表示国王(右)或骑士(左)当前所在的位置,那么灰色的位置表示在一次移动中他们可能到达的位置。国王伤势严重,因此他必须在K个单位时间内得到骑士的救援,否则会挂掉。问国王是否可以在K个单位时间内获得救援,如果可以,最短需要花多少个单位时间。
第一行包含一个整数 T,(1≤T≤50) 代表测试数据的组数,接下来 T 组测试数据。
每组测试数据第一行包含三个整数 N,M,K , 且 2≤N,M≤1000 , 1≤K≤200 。第二行两个整数 Xking,Yking ,对应国王所在方格的坐标。第三行两个整数 Xknight,Yknight ,对应骑士所在方格的坐标。其中 1≤Xking,Xknight≤N,1≤Yking,Yknight≤M ,保证骑士与国王一开始不在同一个方格内且他们都可以移动。:
对于每组测试数据,输出两行:
第一行输出:"Case #i:"。 i 代表第 i 组测试数据。
第二行输出测试数据的结果,如果国王可以得到救援,则输出最快需要花多少个单位时间。否则,输出“OH,NO!”。
2 3 2 1 1 1 3 1 3 3 1 1 1 1 2
Case #1: 1 Case #2: OH,NO!
这个题感觉还是很有意思的。
注意到马跳到一个位置所需步数的奇偶性是不能发生改变的,因为其每跳一步x+y的奇偶性是一定会发生改变的。而对于国王来说,如果国王走k步能到一个位置,那么国王走>=k步一定能到这个位置。所以我们可以首先BFS出王和马到一个位置的最短步数,然后枚举每一个位置。判断一下,如果是王先到这里,那么马到这里的步数就是它们在这里相遇的最短步数;如果是马先到这里,那么最小的大于等于王的步数且与马的最短步数奇偶性相同的数就是王和马在这里相遇的最短时间。
#include<cstdio> #include<iostream> using namespace std; #include<cstring> int d[2][1005][1005]; int qx[1000005],qy[1000005]; int dx[2][10]={{1,2,1,2,-1,-2,-1,-2},{1,1,1,0,0,-1,-1,-1}},dy[2][10]={{2,1,-2,-1,2,1,-2,-1},{1,0,-1,1,-1,1,0,-1}}; int N,M; bool check(int x,int y){ return x>0&&x<=N&&y>0&&y<=M; } int main(){ int T,K; scanf("%d",&T); int x[5],y[5],h,t,i,j,D,ans,tmp; for(int Case=1;Case<=T;++Case){ scanf("%d%d%d%d%d%d%d",&N,&M,&K,x+1,y+1,x,y); memset(d,127,sizeof(d)); for(D=0;D<2;++D){ qx[0]=x[D],qy[0]=y[D],d[D][x[D]][y[D]]=0; for(h=0,t=1;h!=t&&d[D][qx[h]][qy[h]]<K;++h) for(i=0;i<8;++i) if(check(qx[t]=qx[h]+dx[D][i],qy[t]=qy[h]+dy[D][i])&&d[D][qx[t]][qy[t]]>1E5){ d[D][qx[t]][qy[t]]=d[D][qx[h]][qy[h]]+1; ++t; } } ans=0x7fffffff; for(i=N;i;--i) for(j=M;j;--j){ if(d[0][i][j]<=d[1][i][j])ans=min(ans,d[1][i][j]+(d[0][i][j]&1^d[1][i][j]&1)); else if(d[0][i][j]>1)ans=min(ans,d[0][i][j]); } printf("Case #%d:\n",Case); if(ans<=K)printf("%d\n",ans); else puts("OH,NO!"); } }