2015百度之星资格赛1005

来源:互联网 发布:淘宝上有没有卖视频的 编辑:程序博客网 时间:2024/05/22 12:25

题目名称:下棋

题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=584&pid=1005

Problem Description

NM的棋盘上有一个受伤的国王与一个要去救援国王的骑士,他们每个单位时间必须同时移动一次寻找对方。如下图所示,黑色的图例表示国王(右)或骑士(左)当前所在的位置,那么灰色的位置表示在一次移动中他们可能到达的位置。国王伤势严重,因此他必须在K个单位时间内得到骑士的救援,否则会挂掉。问国王是否可以在K个单位时间内获得救援,如果可以,最短需要花多少个单位时间。

Input

第一行包含一个整数T,1T50代表测试数据的组数,接下来T组测试数据。

每组测试数据第一行包含三个整数N,M,K, 且2N,M10001K200。第二行两个整数Xking,Yking,对应国王所在方格的坐标。第三行两个整数Xknight,Yknight,对应骑士所在方格的坐标。其中1Xking,XknightN,1Yking,YknightM,保证骑士与国王一开始不在同一个方格内且他们都可以移动。:

Output

对于每组测试数据,输出两行:

第一行输出:"Case #i:"。i代表第i组测试数据。

第二行输出测试数据的结果,如果国王可以得到救援,则输出最快需要花多少个单位时间。否则,输出“OH,NO!”。

Sample Input
23 2 11 13 13 3 11 11 2 
Sample Output
Case #1:1Case #2:OH,NO!


思路:先对国王和骑士bfs,推出所有走到可能。然后再寻找最少时间的(这道题感觉还不错,可惜hdu没得提交了)


代码如下:

#include <queue>#include <cstdio>#include <string>#include <cstring>#include <iostream>#define clr(a,val) memset(a,val,sizeof(a))using namespace std;const int maxn = 1005;const int INF = 0x3f3f3f3f;struct SPoint{    int x,y,step;};int N,M,K;SPoint Knight,King,Now,Next;queue<SPoint>Que;int Map_Knight[maxn][maxn],Map_King[maxn][maxn];bool vis[maxn][maxn];const int dirX_Knight[8] = {-1,-2,-2,-1,1,2,2,1};const int dirY_Knight[8] = {-2,-1,1,2,-2,-1,1,2};const int dirX_King  [8] = {-1,0,-1,1,-1,1,0,1 };const int dirY_King  [8] = {-1,-1,0,1,1,-1,1,0 };bool Over_Bound(const SPoint &p){    return p.x <= 0 || p.y <= 0 || p.x > N || p.y > M;}void BFS_Knight(){    clr(vis,false);    clr(Map_Knight,-1);    while(!Que.empty()) Que.pop();    Que.push(Knight);    vis[Knight.x][Knight.y] = true;    while(!Que.empty())    {        Now = Que.front();        Map_Knight[Now.x][Now.y] = Now.step;        for(int i = 0; i < 8; i++)        {            Next.x = Now.x + dirX_Knight[i];            Next.y = Now.y + dirY_Knight[i];            Next.step = Now.step + 1;    //Next.step > K 剪枝处理            if(Over_Bound(Next) || vis[Next.x][Next.y] || Next.step > K)                continue;            vis[Next.x][Next.y] = true;            Que.push(Next);        }        Que.pop();    }}void BFS_King() {    clr(vis,false);    clr(Map_King,-1);    while(!Que.empty()) Que.pop();    Que.push(King);    vis[King.x][King.y] = true;    while(!Que.empty())    {        Now = Que.front();        Map_King[Now.x][Now.y] = Now.step;        for(int i = 0; i < 8; i++)        {            Next.x = Now.x + dirX_King[i];            Next.y = Now.y + dirY_King[i];            Next.step = Now.step + 1;    //Next.step > K 剪枝处理            if(Over_Bound(Next) || vis[Next.x][Next.y] || Next.step > K)                continue;            vis[Next.x][Next.y] = true;            Que.push(Next);        }        Que.pop();    }}int main(){    int t,cas = 0,ans;    cin>>t;    while(t--)    {        cin>>N>>M>>K;        cin>>King.x>>King.y;        cin>>Knight.x>>Knight.y;        King.step = Knight.step = 0;        BFS_Knight();        BFS_King();        ans = INF; //初始化为无穷大//关键得好好理解下面的代码~        for(int i = 1; i <= N; i++)        {            for(int j = 1; j <= M; j++)            {                int& Step_King = Map_King[i][j], &Step_Knight = Map_Knight[i][j];                if(Step_King == -1 || Step_Knight == -1) continue;//分类的主要依据就是国王的走法和骑士不同//如果国王比骑士先到该点,国王可以现在该点附近转一下,并不影响骑士到达该点的步数~                if(Step_Knight > Step_King)                {                    ans = min(ans, Step_Knight);                    continue;                }//如果国王比骑士到达该点要多走的步数为奇数                if((Step_King - Step_Knight) & 1)                {                    ans = min(ans,Step_King + 1);                    continue;                }//如果国王比骑士到达该点要多走的步数为偶数                ans = min(ans,Step_King);                continue;            }        }        printf("Case #%d:\n",++cas);        if(ans > K) printf("OH,NO!\n");        else printf("%d\n",ans);    }    return 0;}




0 0
原创粉丝点击