BFS法:
从我们最开始的地方开始遍历,一开始将这个初始位置放在一个队列里面,然后开始遍历这个队列,从初始位置开始将可以到达的状态保存在队列里面,直到没有状态可以到达的时候,我们就将这个初始位置弹出队列,然后在进行队列遍历直到我们找到答案位置。(每次判断该次状态是否之前有达到过)
1、马走棋盘
问题描述:在一个n*m的棋盘上,给出马的初始位置,然后看棋盘上的位置马最少走几步可以到达,然后输出棋盘上马可以到达最少次数的矩阵,如果不可以到达则改点位置为-1;
解题思路:这里我看到是最少到达步数,所以考虑到了BFS来解决最少问题,这里就可以对马的位置进行BFS遍历。
代码解决:
#include<iostream>
#include<queue>
using namespace std;
int xx[]={1,2,1,2,-1,-2,-1,-2};//马可以的八个方向
int yy[]={2,1,-2,-1,2,1,-2,-1};
int chessboard[10][10];//定义的棋盘
int vis[10][10];//用来记录棋盘的每个位置是否走过
queue<int> a;//定义队列因为有x,y两个数据定义两个,这里可以采用结构体
queue<int> b;
int pd(int x,int y)//判断是否超出棋盘,这里我是从1,1开始接受数据的
{
if(x<=3&&x>=1&&y<=3&&y>=1)
{
return 1;
}
return 0;
}
void bfs(int x,int y)
{
chessboard[x][y]=0;
vis[x][y]=1;
a.push(x);
b.push(y);
while(!a.empty())
{
int sx=a.front();
int sy=b.front();
for(int i=0;i<8;i++)
{
int x1=sx+xx[i];
int y1=sy+yy[i];
if(pd(x1,y1)==1&&vis[x1][y1]==0)//判断位置是否在棋盘上和棋盘上该位置是否遍历了,
{
chessboard[x1][y1]=chessboard[sx][sy]+1;//该位置的步数为之前位置加1即可!
vis[x1][y1]=1;
a.push(x1);
b.push(y1);
}
}
a.pop();
b.pop();
}
}
int main()
{
int n,m,x,y;
cin>>n>>m>>x>>y;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
chessboard[i][j]=-1;//初始化棋盘
vis[i][j]=0;
}
bfs(x,y);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<chessboard[i][j]<<' ';
}
cout<<endl;
}
return 0;
}
2、八数码问题
2 0 3 1 2 3
1 8 4 ------------------------》 8 0 4
7 6 5 7 6 5
将例如左边的状态通过移动转化到右边的状态;(0代表空格)
解题思路:这道题我把空格看做可以和周围其他数字进行交换的,对空格初始的位置进行BFS,然后知道我们找到答案位置,这里我是将每次得到的状态保存在三位数组里面,后面也会用来遍历是否当前状态是否在之前的状态之中;
代码
#include<iostream>
#include<queue>
#include<stdio.h>
using namespace std;
int xx[]={0,1,0,-1};//为可以移动的四个方向
int yy[]={1,0,-1,0};
int chessboard[1000001][4][4];//用来保存每次移动到达状态
int top=0,top1=0;
int num[100][4],tt=0;//用来保存从一个状态可以达到的其它状态比如num[0][1]=2说明从0即初始状态可到达
queue<int> a; //2状态;
queue<int> b;
int pd(int x)//判断是否到达目标状态
{
if(chessboard[x][1][1]==1&&chessboard[x][1][2]==2&&chessboard[x][1][3]==3
&&chessboard[x][2][3]==4&&chessboard[x][3][3]==5&&chessboard[x][3][2]==6
&&chessboard[x][3][1]==7&&chessboard[x][2][1]==8)
return 1;
return 0;
}
int wzpd(int x,int y)//判断是否在棋盘上
{
if(x>=1&&x<=3&&y>=1&&y<=3)
{
return 1;
}
return 0;
}
int cf(int chess[4][4])//检查当前状态是否在之前有过的状态之中
{
for(int x=0;x<=top1;x++)
{
int flag=1;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
if(chessboard[x][i][j]==chess[i][j])
{
flag=1;
}
else
{
flag=0;
goto loop;
}
}
}
if(flag==1)
{
return 0;
}
loop:;
}
return 1;
}
void BFS(int h,int g)//开始进行BFS遍历
{
a.push(h);
b.push(g);
while(!a.empty())
{
int x=a.front();
int y=b.front();
for(int i=0;i<4;i++)
{
int x1=x+xx[i];
int y1=y+yy[i];
if(wzpd(x1,y1)==1)
{
int chess1[4][4];
for(int k=1;k<=3;k++)
{
for(int l=1;l<=3;l++){
chess1[k][l]=chessboard[top][k][l];
}
}
for(int k=1;k<=3;k++)
{
for(int l=1;l<=3;l++){
cout<<chess1[k][l]<<' ';
}
cout<<endl;
}
int temp;
temp=chess1[x][y];
chess1[x][y]=chess1[x1][y1];
chess1[x1][y1]=temp;
if(cf(chess1)==1)
{
cout<<"选择第"<<top<<"个来进行扩展"<<endl;
for(int u=1;u<=3;u++)
{
for(int c=1;c<=3;c++)
{
cout<<chess1[u][c]<<' ';
}
cout<<endl;
}
top1++;
num[tt][i]=top1;
for(int q=1;q<=3;q++)
{
for(int p=1;p<=3;p++)
{
chessboard[top1][q][p]=chess1[q][p];
}
cout<<endl;
}
if(pd(top1)==1)
{
return ;
}
a.push(x1);
b.push(y1);
}
else
{
cout<<"*******************已经存在了**********"<<endl;
}
}
}
a.pop();
b.pop();
top++;
tt++;
}
}
int main()
{
int stratx,straty;
for(int i=1;i<=3;i++)
{
for(int j=1;j<=3;j++)
{
cin>>chessboard[0][i][j];
if(chessboard[0][i][j]==0)
{
stratx=i;
straty=j;
}
}
}
BFS( stratx, straty);
int lj[100],kk=2;
lj[0]=top1;
lj[1]=top;
while(top!=0)
{
for(int i=0;i<=top;i++)
{
for(int j=0;j<4;j++)
{
if(num[i][j]==top)
{
lj[kk++]=i;
top=i;
if(top==0)
{
goto loop;
}
}
}
}
}
loop:;
int step=1;
cout<<endl<<endl<<"开始:"<<endl;
for(int i=kk-1;i>=0;i--)
{
for(int x=1;x<=3;x++)
{
for(int y=1;y<=3;y++)
{
cout<<chessboard[lj[i]][x][y]<<' ';
}
cout<<endl;
}
cout<<endl;
if(i!=0)
{
cout<<"第"<<step++<<"步"<<':'<<endl;
}
//cout<<endl;
}
}
```