原文链接: hdu2612 Find a way
上一篇: 输出矩阵的周围元素
下一篇: 分油
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 <cstdio>
#include <queue>
using namespace std;
int n,m;
char mp[222][222];
int dir[4][2]={-1,0,1,0,0,-1,0,1};
bool vis[2][222][222];
int dis[2][222][222];
struct Node{
int k,x,y,step;
Node(){ }
Node(int x,int y,int step):x(x),y(y),step(step){}
};
void setVis(Node& a){
vis[a.k][a.x][a.y]=1;
}
bool check(Node& a){
return a.x<n && a.y<m && a.x>=0 && a.y>=0 && vis[a.k][a.x][a.y]==0 && mp[a.x][a.y]!='#';
}
void bfs(Node& start){
queue<Node> q;
q.push(start);
setVis(start);
while( !q.empty() ){
Node t = q.front();
q.pop();
if(mp[t.x][t.y]=='@'){
dis[t.k][t.x][t.y]=t.step;
}
//上下左右
Node next;
for(int k=0;k<4;k++){
next.k=t.k;
next.x=t.x+dir[k][0];
next.y=t.y+dir[k][1];
next.step=t.step+1;
if(check(next)){
q.push(next);
setVis(next);
}
}
}
}
int main(int argc, char *argv[])
{
while (scanf("%d %d",&n,&m)==2 ){
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%s",mp[i]);
Node ystart,mstart;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='Y'){
ystart.k=0,ystart.x=i,ystart.y=j,ystart.step=0;
}
if(mp[i][j]=='M'){
mstart.k=1,mstart.x=i,mstart.y=j,mstart.step=0;
}
}
}
//分别广搜
bfs(ystart);
bfs(mstart);
int mincnt=1<<20;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
if(mp[i][j]=='@' && vis[0][i][j]==1 && vis[1][i][j]==1 && mincnt>dis[0][i][j]+dis[1][i][j])
mincnt=dis[0][i][j]+dis[1][i][j];
}
printf("%d\n",mincnt*11);
}
return 0;
}