Problem C: 【宽搜入门】8数码难题

Description

初始状态的步数就算1,哈哈

输入:第一个3*3的矩阵是原始状态,第二个3*3的矩阵是目标状态。
输出:移动所用最少的步数

Input

2 8 3
1 6 4
7 0 5
1 2 3
8 0 4
7 6 5

Output

6

参考链接:问题 C: 【宽搜入门】8数码难题

最终AC代码如下:

#include <bits/stdc++.h>
using namespace std;
int final[3][3];
int dir[4][2]={{0, -1},{-1, 0},{0, 1},{1, 0}}; //方向 
struct Node{
    int x, y, step, pdir, M[3][3]; //pdir记录上一次的方向 M当前的矩阵状态 
}now, nex;
bool judge(){
    int i, j;
    for(i=0; i<3; i++){
        for(j=0; j<3; j++) if(nex.M[i][j] != final[i][j]) return false;
    }
    return true;
}
int BFS(){
    int i, t, ti, tj;
    now.step = 1;
    now.pdir = 8; //初始化一个方向 注意范围不能是-2至6! 
    queue<Node> q;
    q.push(now);
    while(!q.empty()){
        now = q.front();
        q.pop();
        for(i=0; i<4; i++){
            if(abs(i-now.pdir) == 2) continue; //表明又要回到上一个状态 
            nex.x = now.x + dir[i][0];
            nex.y = now.y + dir[i][1];
            if(nex.x<0 || nex.x>2 || nex.y<0 || nex.y>2) continue; //位置不合理 
            nex.pdir = i; //记录方向
            nex.step = now.step + 1; //步长加1 
            for(ti=0; ti<3; ti++){ //复制矩阵 
                for(tj=0; tj<3; tj++) nex.M[ti][tj] = now.M[ti][tj];
            }
            //表示走一步 达到下一个状态 
            t = nex.M[now.x][now.y];
            nex.M[now.x][now.y] = nex.M[nex.x][nex.y];
            nex.M[nex.x][nex.y] = t;
            if(judge()) return nex.step;
            q.push(nex);
        }
    }
    return -1; //别忘了遍历完,找不到的情况
}
int main(){
    int i, j;
    for(i=0; i<3; i++){
        for(j=0; j<3; j++){
            scanf("%d", &now.M[i][j]);
            if(now.M[i][j] == 0) now.x=i, now.y=j;
        }
    }
    for(i=0; i<3; i++){
        for(j=0; j<3; j++) scanf("%d", &final[i][j]);
    }
    printf("%d\n", BFS());
    return 0;
}

注意:题目描述得比较简单,因此很多重要信息没有给出:比如,可能有不存在的情况需要返回-1,输入的0表示图片中的空格。

总结:自己在写的时候,是直接再矩阵中改变状态,因此到后面就写不去。然后,参考别人的代码,发现采用的方法是:每走一步产生的状态都存在一个数组中。但是,这里要注意,必须记录该状态是从哪个方向转化的,避免此次选择的方向会再次回到之前的状态。

通过这个题,对BFS()算法有了一点新领悟:while循环每次遍历过程中,只要满足某个条件就会有新的元素入队,直到找到答案或者搜索完。这里,找答案的过程,其实是多路进行的,即在找到答案前,是有一些不可避免的“冗余操作”。我自己的理解是,既然不知道哪条路径可以找到答案,那么我就把第一层所有情况遍历完后,再进入到第二层,并依此类推。而DFS()搜索则是典型的“不撞南墙不回头”。

猜你喜欢

转载自www.cnblogs.com/heyour/p/12672651.html