Description
小明最近喜欢玩一个游戏。给定一个n * m的棋盘,上面有两种格子#和@。游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格。如果移动到同一类型的格子,则费用是0,否则费用是1。请编程计算从起始位置移动到目标位置的最小花费。
Input
输入文件有多组数据。
输入第一行包含两个整数n,m,分别表示棋盘的行数和列数。
输入接下来的n行,每一行有m个格子(使用#或者@表示)。
输入接下来一行有四个整数x1, y1, x2, y2,分别为起始位置和目标位置。
当输入n,m均为0时,表示输入结束。
Output
对于每组数据,输出从起始位置到目标位置的最小花费。每一组数据独占一行。
Sample Input
2 2
@#
#@
0 0 1 1
2 2
@@
@#
0 1 1 0
0 0
@#
#@
0 0 1 1
2 2
@@
@#
0 1 1 0
0 0
Sample Output
2
0
0
HINT
对于100%的数据满足:1 < = n, m <= 500。
题解:直接spfa就好。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=510;
char ch;
bool f[N*N];
int n,m,map[510][510],point[N*N],next[N*N*10],tot,dis[N*N],l[N*N*10];
int xi[4]={-1,0,0,1},yi[4]={0,-1,1,0};
struct S{int st,en,va;}aa[N*N*10];
inline void add(int x,int y,int z){
tot+=1;next[tot]=point[x];point[x]=tot;
aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;
}
inline void SPFA(int x){
int h,t,u,i;
memset(f,1,sizeof(f));
memset(dis,127/3,sizeof(dis));
h=t=1;l[h]=x;dis[x]=0;
while(h<=t){
u=l[h]; f[u]=true;
for(i=point[u];i;i=next[i])
if(dis[aa[i].en]>dis[u]+aa[i].va){
dis[aa[i].en]=dis[u]+aa[i].va;
if(f[aa[i].en]){
f[aa[i].en]=false;
l[++t]=aa[i].en;
}
}
h+=1;
}
}
int main(){
while(scanf("%d%d",&n,&m)==2){
if(n==m&&n==0) break;
int i,j,x1,y1,x2,y2,k;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j){
while(1){
scanf("%c",&ch);
if(ch=='@'||ch=='#') break;
}
if(ch=='@') map[i][j]=1;
if(ch=='#') map[i][j]=2;
}
tot=0;
memset(point,0,sizeof(point));
memset(next,0,sizeof(next));
for(i=1;i<=n;++i)
for(j=1;j<=m;++j)
for(k=0;k<4;++k){
int xx=i+xi[k],yy=j+yi[k];
if(xx>0&&xx<=n&&yy>0&&yy<=m)
add(m*(i-1)+j,m*(xx-1)+yy,abs(map[i][j]-map[xx][yy]));
}
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1+=1;y1+=1;x2+=1;y2+=1;
SPFA((x1-1)*m+y1);
printf("%d\n",dis[(x2-1)*m+y2]);
}
}