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
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.
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
代码:(该代码错误!虽然能提交通过,但是代码是错的!下面已经改正,并附上了正确代码)
#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;
}