下棋
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;
}