题目描述
小明最近喜欢玩一个游戏。给定一个n×m的棋盘,上面有两种格子#
和@
。游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格。如果移动到同一类型的格子,则费用是00,否则费用是11。请编程计算从起始位置移动到目标位置的最小花费。
输入格式
输入文件有多组数据。
输入第一行包含两个整数n,m,分别表示棋盘的行数和列数。
输入接下来的n行,每一行有m个格子(使用#
或者@
表示)。
输入接下来一行有四个整数x1,y1,x2,y2,分别为起始位置和目标位置。
当输入n,m均为0 0时,表示输入结束。
输出格式
对于每组数据,输出从起始位置到目标位置的最小花费。每一组数据独占一行。
输入输出样例
输入
2 2 @# #@ 0 0 1 1 2 2 @@ @# 0 1 1 0 0 0
输出
2 0
思路:双端队列,把所有得分相比上一个不增加的点丢队头,相比于上个点增加的点丢队尾,这样就能找到到终点的最小值,不能使用正常的dfs,因为每条路的边权是不同的。
AC code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
using namespace std;
typedef pair<int,int>PII;
char g[501][501];
int spend[501][501];
int n,m,s1,s2,e1,e2;
deque <PII>q;
int bfs(int x,int y)
{
memset(spend,-1,sizeof spend);
int dx[]={1,0,0,-1};
int dy[]={0,1,-1,0};
q.push_front({x,y});
spend[x][y]=0;
while(q.size())
{
PII t=q.front();
q.pop_front();
for(int i=0;i<4;i++)
{
int a=t.first+dx[i],b=t.second+dy[i];
if(a<0||a>=n||b<0||b>=m) continue;
if(spend[a][b]>=0) continue;
if(g[t.first][t.second]==g[a][b])
{
q.push_front({a,b});
spend[a][b]=spend[t.first][t.second];
}
else
{
q.push_back({a,b});
spend[a][b]=spend[t.first][t.second]+1;
}
if(a==s2&&b==e2) return spend[a][b];
}
}
}
int main()
{
while(cin>>n>>m,m||n)
{
for(int i=0;i<n;i++)
scanf("%s",g[i]);
scanf("%d %d %d %d",&s1,&e1,&s2,&e2);
q.clear();
int res=bfs(s1,e1);
printf("%d\n",res);
}
return 0;
}