2015百度之星资格赛1005
题目名称:下棋
题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=584&pid=1005
思路:先对国王和骑士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; }
本文版权归作者本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.