思路:题目意思比较明确,思路是采用优先队列每次取出次数最小的点进行bfs,这里要注意一个坑,(因为这个wa了n发。。。)遇到2~9的点时,要立即入队所有值相同的点,而不是先把这个点入队等过一段时间排到这个点时再把相同值的点入队,这里举一个简单的例子
S00
33E
000
这里第一次入队(0,1)位置的0和(1,0)位置的3,如果不将另一个3入队,出队先出0的话,这时另一个3就会被访问,但其步数会是1+1,明显是多的,这就造成结果出错了。
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <queue>
using namespace std;
char map[2000][2000];
int vis[2000][2000];
int vis2[100];
struct note
{
int x,y,step;
bool operator < (const struct note &tmp)const
{
return step>tmp.step;
}
};
int dx[] = {0,1,0,-1};
int dy[] = {-1,0,1,0};
int n,ans,flag;
note s,e;
void bfs(note a)
{
priority_queue<note> q;
while(!q.empty())q.pop();
q.push(a);
while(!q.empty())
{
note tmp = q.top();
q.pop();
if(tmp.x==e.x&&tmp.y==e.y)
{
ans = tmp.step;
flag = 1;
break;
};
note dd;
for(int i=0;i<4;i++)
{
dd.x = tmp.x+dx[i];
dd.y = tmp.y+dy[i];
dd.step = tmp.step+1;
if(dd.x>=0&&dd.x<n&&dd.y>=0&&dd.y<n&&!vis[dd.x][dd.y]&&map[dd.x][dd.y]!='1')
{
vis[dd.x][dd.y] = 1;
q.push(dd);
if(map[dd.x][dd.y]!='0'&&map[dd.x][dd.y]!='S'&&!vis2[map[dd.x][dd.y]-'0'])
{
vis2[map[dd.x][dd.y]-'0'] = 1;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(map[i][j]==map[dd.x][dd.y]&&!vis[i][j])
{
note ddd;
ddd.x = i;
ddd.y = j;
ddd.step = dd.step;
vis[i][j] = 1;
q.push(ddd);
}
}
}
}
}
}
}
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
memset(vis,0,sizeof(vis));
memset(vis2,0,sizeof(vis2));
for(int i=0;i<n;i++)
scanf("%s",map[i]);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(map[i][j]=='S')
{
s.x = i;
s.y = j;
s.step = 0;
vis[i][j]=1;
}
if(map[i][j]=='E')
{
e.x = i;
e.y = j;
}
}
flag = 0;
bfs(s);
if(flag)
printf("%d\n",ans);
else
printf("Oh No!\n");
}
}