图论题。
题目要求棋子从左上角走到右下角的最短路。
1 DFS
先考虑用深度优先搜索解决。
注意:我们要判断一下相邻两步的格子颜色,这也决定了下一步的合法性。
可以写出以下核心代码:
void dfs(int x,int y,char c,int step){//x 和 y 表示当前位置,c 表示当前格的颜色,step 表示步数
if(x==n&&y==m){//搜到终点
ans=min(ans,step);//更新答案
return ;
}
vis[x][y]=1;
for(int i=0; i<4; i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&!vis[tx][ty]&&maze[tx][ty]!=c){//判断下一个位置是否合法
dfs(tx,ty,maze[tx][ty],step+1);
vis[tx][ty]=0;//回溯
}
}
}
这是过不了的。
2 BFS
超时了。再改一改,用广度优先搜索解。要注意的点同上。
这样就可以 AC 了。
AC 代码
#include<bits/stdc++.h>
using namespace std;
int dx[]={0,1,-1,0},dy[]={1,0,0,-1};
int n,m;
int dis[505][505];
char maze[505][505];
struct node{
int o,p;
char w;
};//存储状态
void bfs(){
memset(dis,0x3f,sizeof(dis));
queue<node> q;
dis[1][1]=0;
q.push({1,1,maze[1][1]});
while(!q.empty()){
node now=q.front();//当前状态
q.pop();
int x=now.o,y=now.p;
char c=now.w;
if(x==n&&y==m){
return;//搜到终点,结束
}
for(int i=0; i<4; i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&dis[tx][ty]>dis[x][y]+1&&maze[tx][ty]!=c){//判断下一个位置是否合法
q.push({tx,ty,maze[tx][ty]});
dis[tx][ty]=dis[x][y]+1;//更新最短路
}
}
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
cin>>maze[i][j];
}
}
bfs();
if(dis[n][m]==0x3f3f3f3f) printf("-1");//无解
else printf("%d",dis[n][m]);
return 0;
}
3 补充
其实这道题还挺模板的。适合广度优先搜索新手练习。
推荐一些广度优先搜索题目:
浙公网安备 33010602011771号