来源:http://poj.org/problem?id=2312
思路:这道题可以用BFS进行解答,遇到E需要走两步,而遇到B要先打掉B再走,可以看作需要走两步。但与普通的BFS不同,这里的点可以重复进队列,类似于spfa,不断修改点上的步数,最后得到最优解。
代码:
#include <stdio.h>
int g[301][301],f[301][301],f1[301][301];
//f数组用来判断点是否在队列中,f1数组用来储存到达点的最少步数
struct rec{
int x,y;
}q[100000];
const int fx[4]={0,0,1,-1};
const int fy[4]={1,-1,0,0};
int n,m,sx,sy,tx,ty,s,t,x1,y1,x,y;
int doing(void)
{
s=0;t=1;q[1].x=sx;q[1].y=sy;
f[sx][sy]=1;f1[sx][sy]=0;
while(s<t)
{
s++;
x=q[s].x;y=q[s].y;
f[x][y]=0;
for(int i=0;i<4;i++)
{
x1=x+fx[i];y1=y+fy[i];
if(1<=x1&&x1<=n&&1<=y1&&y1<=m&&g[x1][y1]!=-1)
{
if(f1[x1][y1]>f1[x][y]+g[x1][y1])
{
f1[x1][y1]=f1[x][y]+g[x1][y1];
if((x1!=tx||y1!=ty)&&f[x1][y1]==0)
{
t++;
q[t].x=x1;q[t].y=y1;
f[x1][y1]=1;
}
}
}
}
}
if(f1[tx][ty]==1000000000) printf("-1\n");
else printf("%d\n",f1[tx][ty]);
return 0;
}
int main()
{
char c;
scanf("%d%d\n",&n,&m);
while(n!=0&&m!=0)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%c",&c);
f[i][j]=0;
f1[i][j]=1000000000;
if(c=='Y')
{
sx=i;sy=j;
g[i][j]=1;
}
if(c=='T')
{
tx=i;ty=j;
g[i][j]=1;
}
if(c=='S') g[i][j]=-1;
if(c=='E') g[i][j]=1;
if(c=='B') g[i][j]=2;
if(c=='R') g[i][j]=-1;
}
scanf("\n");
}
doing();
scanf("%d%d\n",&n,&m);
}
return 0;
}