下棋
Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
N?M的棋盘上有一个受伤的国王与一个要去救援国王的骑士,他们每个单位时间必须同时移动一次寻找对方。如下图所示,黑色的图例表示国王(右)或骑士(左)当前所在的位置,那么灰色的位置表示在一次移动中他们可能到达的位置。国王伤势严重,因此他必须在K个单位时间内得到骑士的救援,否则会挂掉。问国王是否可以在K个单位时间内获得救援,如果可以,最短需要花多少个单位时间。
Input
第一行包含一个整数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,保证骑士与国王一开始不在同一个方格内且他们都可以移动。:
Output
对于每组测试数据,输出两行:
第一行输出:"Case #i:"。i代表第i组测试数据。
第二行输出测试数据的结果,如果国王可以得到救援,则输出最快需要花多少个单位时间。否则,输出“OH,NO!”。
Sample Input
2 3 2 1 1 1 3 1 3 3 1 1 1 1 2
Sample Output
Case #1: 1 Case #2: OH,NO!
用BFS进行遍历,骑士每走到一个格子,就判断他们能不能在这个点相遇,如果可以,算出他们的最小时间(如果骑士先到达那个点,他可以来回走等国王,国王可以通过走斜步来改变步数的奇偶性,可以说他们最后他们一定能相遇,最小时间大于k的话就GG了)
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #include<math.h> #include<stdlib.h> using namespace std; #define N 1000+10 #define inf 0xfffffff struct node { int x,y,t; }; bool used[N][N]; int minn,sx,sy,n,m,k; int dir[8][2]={-2,-1,-1,-2,-1,2,-2,1,1,-2,2,-1,1,2,2,1}; int ex,ey; int dis(int x,int y,int t) { int d=max(abs(x-ex),abs(y-ey));//国王走斜步来使时间最小 if(d==0)//如果国王起点就在(x,y) { if(t%2==0) return 0; } d=abs(d-t); return d; } void bfs(int sx,int sy) { queue<node>q; node temp; temp.x=sx; temp.y=sy; temp.t=0; memset(used,false,sizeof(used)); used[sx][sy]=true; q.push(temp); while(!q.empty()) { node tmp=q.front(); q.pop(); int d=dis(tmp.x,tmp.y,tmp.t); if(d%2==0) { minn=min(minn,d+tmp.t); } else { minn=min(minn,d+tmp.t+1); } for(int i=0;i<8;i++) { node s; s.x=dir[i][0]+tmp.x; s.y=dir[i][1]+tmp.y; s.t=tmp.t; if(s.t>k||s.x<1||s.x>n||s.y<1||s.y>m||used[s.x][s.y]) continue; used[s.x][s.y]=true; s.t++; q.push(s); } } } int main() { int T; scanf("%d",&T); for(int i=1;i<=T;i++) { scanf("%d%d%d",&n,&m,&k); scanf("%d%d",&ex,&ey); scanf("%d%d",&sx,&sy); minn=inf; bfs(sx,sy); printf("Case #%d:\n",i); if(minn>k) printf("OH,NO!\n"); else printf("%d\n",minn); } return 0; }
时间: 2024-10-08 21:40:47