链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3478
Binary Land is a very simple action title for the Famicom with an interesting twist. You control, not one, but two penguins, Gurin (male) and Malon (female), who are in love with each other. While you are in direct control of one penguin, you indirectly control the other penguin, who moves in a mirror image fashion from the original penguin. When you move your penguin left, the other moves right, and vice versa. The goal of the game is to move both penguins from their own origins to the unique caged heart at the same time.
At the beginning of each stage, you can choose which penguin to control directly. There are many walls which stop penguins from moving into them. If a penguin trys to do so, it will remain in the original grid. Besides the caged heart and walls, spider webs are strewn about in the 10×15 maze. If one of the penguins hits the web, it will become stuck in place until the other penguin moves to its neighbour and helps the stuck penguin move from the spider web to its grid. This process costs 11 seconds. Generally, it costs 5 seconds to move both penguins simultaneously. But when one of the penguins is stuck, moving the penguin which you directly control takes 2 seconds, while moving the other penguin takes 3 seconds.
What's the earliest time that Gurin and Malon can meet at the caged heart?
Binary Land | Sample 1 | Sample 2 |
Sample 3 | Sample 4 | Sample 5 |
There are multiple test cases. The first line of input is an integer T ≈ 100 indicating the number of test cases.
Each test case contains 13 lines. The first 10 lines are the 10×15 maze, the 11th line is the origin of Gurin, the 12th line is the origin of Malon, and the 13th line is always a blank line. The maze is made up of unique caged heart ('H'), spider webs ('O'), walls ('X'), and empty grids ('.'). The origins of penguins cannot be walls.
For each test case, output the earliest time, or -1 when it's impossible.
5 .......H....... .XXX.XXX.XXX.XX XX.X.X.XXX.X.X. ..O....X....... .XXXXX.X.XXXXX. .......X....O.. XX.X.X.X.X.X.XX .......X....... .XXXXXXXXXXXXX. .......X....... 1 15 1 1 .......H....... .X.X.XXXXX.X.X. .X.X.X.X.XXXXX. ...X..OX...X... .XXX.XXXXX.X.XX .......X....... XX.XXX.X.XXXXX. O..X...X....... .X.X.X.XXX.X.XX .....X.X....... 10 9 10 7 ...XO..H....... OX.X.X.X.X.X.XX OXOX.XOX.X.X.X. OX...X.XO..X..O .XXXXXXX.XXX.XX .O.XO..X..O.... .X.X.X.XXX.XXX. OX.X.XOXO..X.O. .XOX.X.X.X.X.X. .X...X.X.....X. 10 9 10 7 .......H.....X. .XXX.XXXXX.X.X. XX.X.X.X.X.X.X. .......XO..X... .XXXXX.XXX.XXX. .......X.X..... .X.X.XXX.XXX.XX .......X...X..O XXXXXX.X.X.X.X. .......X.X..... 1 10 1 4 .......H....... .X.X.X.X.X.X.X. .X.X.X.X.X.X.X. .......X....... .X.X.X.X.X.X.X. .......X....... .X.X.X.X.X.X.X. .......X....... .X.X.X.X.X.X.X. ......OX....... 10 1 10 7
35 140 -1 40 99
题意:给你地图‘X’是墙,‘.’是路,和两只公母企鹅的坐标,开始两只企鹅不会在墙里。他们如果没被困,或者没走到地图边缘,或者没被墙挡住,那么都是同步走的,上下同相走,左右反向走。求同时走到H点的最小时间。同时走耗时5s。图里有蜘蛛网‘O’,如果有一只被困,那么另一只可能是笨企鹅,也可能是聪明的企鹅,聪明的走一步耗时2s,笨的3s。如果一只企鹅走到另一只企鹅的旁边,可以把另一只救出来,让他到自己的位置。耗时11s。
两只企鹅如果都被困,就失败了。
做法:
bfs,因为不知道哪只是笨的,所以要bfs两次。打的比较麻烦,注意下各种情况就好了。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <stack> #include <queue> #include <vector> #include <deque> #include <set> #include <map> #define INF 999999999 #define eps 0.00001 #define LL __int64d #define pi acos(-1.0) // 10×15 maze, int dir[4][2][2]={ 1,0, 1,0, -1,0, -1,0, 0,1, 0,-1, 0,-1, 0,1 };//一维四个方向 二维 哪只企鹅 三维xy char mp[10][15]; int vis[10][15][10][15];//-1代表没走过, 不是-1代表到达这个状态最小花费的步数 struct point { int x1,y1; int x2,y2; int bu; bool operator <(const point &b)const { return bu>b.bu; } }; int ok(int x,int y) { if(x>=0&&x<10&&y>=0&&y<15&&mp[x][y]!='X') return 1; return 0; } point walk(point nw,int t,int zou)//走, { int xx1,xx2,yy1,yy2; if(zou&1) { xx1=nw.x1+dir[t][0][0]; yy1=nw.y1+dir[t][0][1]; if(ok(xx1,yy1)) { nw.x1=xx1; nw.y1=yy1; } } if(zou&2) { xx2=nw.x2+dir[t][1][0]; yy2=nw.y2+dir[t][1][1]; if(ok(xx2,yy2)) { nw.x2=xx2; nw.y2=yy2; } } return nw; } int low(point gg) { if(vis[gg.x1][gg.y1][gg.x2][gg.y2]==-1||vis[gg.x1][gg.y1][gg.x2][gg.y2]>gg.bu)//判断能否更新vis,可以的话就走,return 1 { vis[gg.x1][gg.y1][gg.x2][gg.y2]=gg.bu; return 1; } return 0; } int near(point gg)//判断两只企鹅是否相邻 { if(abs(gg.x1-gg.x2)+abs(gg.y2-gg.y1)==1) return 1; return 0; } int bfs(point gg) { priority_queue<point> q; gg.bu=0; q.push(gg); point nw; point tem; low(gg); while(!q.empty()) { nw=q.top(); q.pop(); if(nw.x1==nw.x2&&nw.y1==nw.y2&&mp[nw.x1][nw.y1]=='H')//结束 return nw.bu; if(mp[nw.x1][nw.y1]=='O'&&mp[nw.x2][nw.y2]=='O')//都被困 continue; int xx1,xx2,yy1,yy2; if(mp[nw.x1][nw.y1]=='O') // 1被困 { if(near(nw))//相邻,2 救1 { tem=nw; tem.bu=nw.bu+11; tem.x1=tem.x2; tem.y1=tem.y2; if(low(tem)) q.push(tem); } for(int i=0;i<4;i++) { tem=walk(nw,i,2); tem.bu=nw.bu+3; if(low(tem)) q.push(tem); } } else if(mp[nw.x2][nw.y2]=='O') // 1hao 2s { if(near(nw)) { tem=nw; tem.bu=nw.bu+11; tem.x2=tem.x1; tem.y2=tem.y1; if(low(tem)) q.push(tem); } for(int i=0;i<4;i++) { tem=walk(nw,i,1); tem.bu=nw.bu+2; if(low(tem)) q.push(tem); } } else { for(int i=0;i<4;i++) { tem=walk(nw,i,3); tem.bu=nw.bu+5; if(low(tem)) q.push(tem); } } } return INF; } int main() { int t; cin>>t; while(t--) { for(int i=0;i<10;i++) { scanf("%s",mp[i]); } memset(vis,-1,sizeof vis); point gg; cin>>gg.x1; gg.x1--; cin>>gg.y1; gg.y1--; cin>>gg.x2; gg.x2--; cin>>gg.y2; gg.y2--; int ans=bfs(gg); swap(gg.x1,gg.x2); swap(gg.y1,gg.y2); ans=min(ans,bfs(gg)); if(ans==INF) cout<<"-1"<<endl; else cout<<ans<<endl; } return 0; }