[ACM] hdu Find a way
Find a way
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3238 Accepted Submission(s): 1051
Problem Description
Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki.
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest.
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes.
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest.
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes.
Input
The input contains multiple test cases.
Each test case include, first two integers n, m. (2<=n,m<=200).
Next n lines, each line included m character.
‘Y’ express yifenfei initial position.
‘M’ express Merceki initial position.
‘#’ forbid road;
‘.’ Road.
‘@’ KCF
Each test case include, first two integers n, m. (2<=n,m<=200).
Next n lines, each line included m character.
‘Y’ express yifenfei initial position.
‘M’ express Merceki initial position.
‘#’ forbid road;
‘.’ Road.
‘@’ KCF
Output
For each test case output the minimum total time that both yifenfei and Merceki to arrival one of KFC.You may sure there is always have a KFC that can let them meet.
Sample Input
4 4 Y.#@ .... .#.. @..M 4 4 Y.#@ .... .#.. @#.M 5 5 Y..@. .#... .#... @..M. #...#
Sample Output
66 88 66
Author
yifenfei
Source
代码:(该代码错误!虽然能提交通过,但是代码是错的!下面已经改正,并附上了正确代码)
#include <iostream> #include <algorithm> #include <queue> #include <string.h> using namespace std; char map[202][202];//地图 int a[202][202];//保存第一个人Y到各个节点(坐标)的最小步数,有的节点不用访问,下面有说明 int b[202][202];//保存第二个人M int dx[4]={0,0,-1,1}; int dy[4]={1,-1,0,0};//方向 int n,m;//地图大小 int kcount;//KFC一共的个数 int yx,yy,mx,my;//Y的坐标,M的坐标 int flag;//用来判断执行第一个人的BFS还是第二个人的BFS void getmap()//输入地图 { for(int i=0;i<n;i++) for(int j=0;j<m;j++) { cin>>map[i][j]; if(map[i][j]=='@') kcount++; else if(map[i][j]=='Y') { yx=i; yy=j; } else if(map[i][j]=='M') { mx=i; my=j; } } } struct node { int x,y; }; void bfs(int x,int y) { int k=0;//搜索过程中的KFC的个数,初始为0 queue<node>q; node aa,bb; aa.x=x; aa.y=y; if(!flag)//flag=0的时候执行Y的bfs a[x][y]=0; else b[x][y]=0;//flag=1的时候执行M的bfs q.push(aa); while(!q.empty()) { bb=q.front(); q.pop(); if(k==kcount) break;//退出条件 ,当搜索过程中访问过的KFC数量等于整个地图总的KFC数量时就可以退出,剩下的节点不需要再访问 for(int i=0;i<4;i++) { aa.x=bb.x+dx[i]; aa.y=bb.y+dy[i]; if(!flag)//Y的bfs { if(aa.x>=0&&aa.x<n&&aa.y>=0&&aa.y<m&&a[aa.x][aa.y]==0&&map[aa.x][bb.y]!='#') { if(map[aa.x][aa.y]=='@')//搜索过程中遇到KFC,数量加1 k++; a[aa.x][aa.y]=a[bb.x][bb.y]+1; q.push(aa); } } else//M的bfs { if(aa.x>=0&&aa.x<n&&aa.y>=0&&aa.y<m&&b[aa.x][aa.y]==0&&map[aa.x][bb.y]!='#') { if(map[aa.x][aa.y]=='@') k++; b[aa.x][aa.y]=b[bb.x][bb.y]+1; q.push(aa); } } }//for }//while } int main() { while(cin>>n>>m) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); kcount=0; flag=0; getmap(); bfs(yx,yy); flag=1; bfs(mx,my); int minn=1000000; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(map[i][j]=='@') { minn=min(minn,a[i][j]+b[i][j]);//某个KFC地点两者到达的总步数之和,取最小值。 } } cout<<minn*11<<endl; } return 0; }
2014.3.3 修改
最近又重新做这个题,发现上面写的代码虽然能通过,但是错误的!
if(aa.x>=0&&aa.x<n&&aa.y>=0&&aa.y<m&&a[aa.x][aa.y]==0&&map[aa.x][bb.y]!='#')
map[aa.x][bb.y]这里应该是map[aa.x][aa.y]才对,当时不知道为什么会写成那样,而且能通过,更不得其解,但是后来改回来以后,提交竟然通不过了!为这个问题困扰了两天!下午,让老师帮我看看。后来老师出了一个神测试数据。
4 5
@ . # @ .
. . Y # .
@ # M # .
@ . . # @ 这个测试数据用我改后的代码竟然输出为0,后来用别人的其他能在航电上通过的代码测试,输出也是0,但该测试数据结果应该为77才对。这就说明了该题后台测试数据不全面。
后来想了想为什么会输出为0,该测试数据很特殊,因为第四列@和第五列的@在广搜时搜不到!因为被墙#完全隔着,其步数永远是0,后来在遍历全图,取两人在@处最小步数时,肯定是没有搜到的@处最小,因为二者到此处的步数均为0,想加也为0,所以必须得加一个限制条件,取@处二者步数相加和的最小且该@处必须已经被搜过!加上这一句,代码就没问题了。我把上面提到的错误(map[aa.x][bb.y]这里应该是map[aa.x][aa.y]才对)改了以后,又在后面加上了限制条件,再重新提交,Ac了!哎,不容易啊,一桩心事终于了了!
下面附上修改后并优化后的代码:
#include <iostream> #include <algorithm> #include <queue> #include <string.h> using namespace std; char map[202][202];//地图 int a[202][202];//保存第一个人Y到各个节点(坐标)的最小步数,有的节点不用访问,下面有说明 int b[202][202];//保存第二个人M int dx[4]={0,0,-1,1}; int dy[4]={1,-1,0,0};//方向 int n,m;//地图大小 int yx,yy,mx,my;//Y的坐标,M的坐标 void getmap()//输入地图 { for(int i=0;i<n;i++) for(int j=0;j<m;j++) { cin>>map[i][j]; if(map[i][j]=='Y') { yx=i; yy=j; } else if(map[i][j]=='M') { mx=i; my=j; } } } struct node { int x,y; }; void bfs(int x,int y,int num[202][202])//广搜 { queue<node>q; node aa,bb; aa.x=x; aa.y=y; num[x][y]=0; q.push(aa); while(!q.empty()) { bb=q.front(); q.pop(); for(int i=0;i<4;i++) { aa.x=bb.x+dx[i]; aa.y=bb.y+dy[i]; if(aa.x>=0&&aa.x<n&&aa.y>=0&&aa.y<m&&num[aa.x][aa.y]==0&&map[aa.x][aa.y]!='#') { num[aa.x][aa.y]=num[bb.x][bb.y]+1; q.push(aa); } }//for }//while } int main() { while(cin>>n>>m) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); getmap(); bfs(yx,yy,a); bfs(mx,my,b); int minn=1000000; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(map[i][j]=='@'&&b[i][j]!=0)//必须保证此处@被访问过!写成a[i][j]!=0也可以 { minn=min(minn,a[i][j]+b[i][j]);//某个KFC地点两者到达的总步数之和,取最小值。 } } cout<<minn*11<<endl; } return 0; }