我的代码其实是有一丢丢小问题的(我在备注里也写了),我也没改,不过大致思路是正确的。
#include <cstdio>
#include<math.h>
#include<queue>
using namespace std;
//对于这道题,是需要有一个方法来更新地图的,也就是每选一部,就更新一次
//然后对于主函数就是,进行各个方向的判断,这道题dfs和BFS都可以,但是这题是放在BFS上的
//而且又是需要有字符串数组的参与
//这道题最巧妙的地方在于,他不判重复,所以最核心的就是,他只要走满8步。期间都没有问题的话,他就是一定可以的
char mmap[8][8];
int stepx[9]={-1,1,0,0,-1,-1,1,1,0};
int stepy[9]={0,0,-1,1,-1,1,-1,1,0};
//bool mark[8][8]={false};
//写一个方法来判断这个点是否可以
int step;//用来表示记录的个数
bool judge(int x,int y){
if(x<0||x>=8||y<0||y>=8)
return false;//越界
if(mmap[x][y]!='S')
//如果没有被访问过,并且这个点不是石头的话,就可以访问
return true;
else
return false;
}
//在写一个方法更新地图,本来我想的是在先判断这个位置是不是落石,如果是的话,那就把下面一个也变成落石,可是这样的话,就会对地图再一次更新
//可是这样不行,所以是需要从后往前开始移动的(和01背包一个道理)
void updatemap(){
//遍历整个地图
for(int i=7;i>=0;i--)
for(int j=7;j>=0;j--){
if(mmap[i][j]=='S'){
//对他是不是最后一行进行分类,最后一行的话,直接换成*
if(i==7)
mmap[i][j]='.';
else{
//如果不是最后一行的话,这一行变成* 下一行变成S
mmap[i][j]='.';
mmap[i+1][j]='S';
}
}
}
}
//然后开始就是BFS,我将其设置为bool形
bool BFS(int a,int b){
//是需要创建一个队列的
queue<char> p;
p.push(mmap[a][b]);
bool flag;//用来做标记
while(!p.empty()){
//再非空的条件下
flag=false;
char temp=p.front();
if(temp=='A'||step>8)
return true;//到终点直接返回
//这个和普通的有点区别在于,每次对应点实时更新一下,这里出现的错误在于,不是当前的temp,而是当前位置的值,其实已经更新了。。
if(temp=='S')
return false;
//再删去第一个
p.pop();
//再开始判断这些他的左右上下的点
for(int k=0;k<=8;k++){
//如果这个点可以的话,那就进行换位,可是难点在于,怎么换位之后还原呢,换位不是永久性的嘛,现在想的是 弄一个标记,如果可行的话,就进行一次换位
//还是说 再弄一个重复的?
int newa=a+stepx[k];
int newb=b+stepy[k];
if(judge(newa,newb)){
//如果这个点可以的话,就进行换位,还是用那个标记的方法比较好
flag=true;
//然后这个点进栈,并把他标志为访问过了
//mark[newa][newb]=true;
p.push(mmap[newa][newb]);
}
}
if(flag){
//也就是这一层进行过换位的话,那就修改一次图
updatemap();
step+=1;
}
}
return false;
}
int main(){
int n;
scanf("%d",&n);
int q=1;
while(q<=n){
step=0;
//用新学到的写字符串的方法
for(int i=0;i<8;i++)
scanf("%s",mmap[i]);
//mark[7][0]=true;
if(BFS(7,0))
printf("Case #%d: YES\n",q);
else
printf("Case #%d: No\n",q);
q++;
}
}