繁体   English   中英

8回溯拼图

[英]8 Puzzle with Backtracking

我正在从Skiena,编程挑战中读到这本书,在回溯章节之后,有一个关于用回溯来解决15-puzzle的问题,我将它简化为8-puzzle进行实验。 我有这个递归代码,我想知道它是否有机会找到解决方案。 代码有点难看(被警告):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int arr[20][20]={
    {3,1,2},
    {4,0,5},
    {6,8,7}
};

int moveX[20]={1,1,1,0,0,-1,-1,-1};
int moveY[20]={0,1,-1,1,-1,0,1,-1};
int depth=0;

int findRow(){
    int i,j;
    for(i=0;i<4;i++){
        for(j=0;j<4;j++){
            if(arr[i][j]==0){
                return i;
            }
        }
    }
}

int findCol(){
    int i,j;
    for(i=0;i<3;i++){
        for(j=0;j<3;j++){
            if(arr[i][j]==0){
                return j;
            }
        }
    }
}

void print(){
    int i,j;
    for(i=0;i<3;i++){
        for(j=0;j<3;j++){
            printf("%i ",arr[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int isReady(){
    if(arr[0]==1 && arr[1]==2 && arr[2]==3 && arr[3]==4 && arr[4]==5 && arr[5]==6 && arr[6]==7 && arr[7]==8){
        return 1;
    }
    else return 0;
}

void perm(int row,int col,int n){
    if(n>=9){
        print();
        if(isReady())
            printf("Finished");
        depth++;

        return;
    }

    int i=0;int diffX,diffY,temp;
    int r=findRow();
    int c=findCol();
    temp=arr[r][c];
    arr[r][c]=arr[row][col];
    arr[row][col]=temp;
    for(i=0;i<8;i++){
        diffX=row+moveX[i];
        diffY=col+moveY[i];
        if(diffX>=0 && diffX<4 && diffY>=0 && diffY<4){
            perm(diffX,diffY,n+1);
        }
    }
    temp=arr[r][c];
    arr[r][c]=arr[row][col];
    arr[row][col]=temp;
}

int main()
{
    perm(0,0,0);
    return 0;
}

我的问题是,这个代码是否有机会找到解决方案,其次,任何人都可以在合理的时间内解决这个难题吗?

你有五个问题。 首先, isReady函数不正确。 它应该如下所示:

int isReady(){
    if(arr[0][0]==1 && arr[0][1]==2 && arr[0][2]==3 &&
            arr[1][0]==4 && arr[1][1]==5 && arr[1][2]==6 &&
            arr[2][0]==7 && arr[2][1]==8){
        return 1;
    }
    else return 0;
}

其次,你使用diffXdiffY超越你的拼图界限。 你需要改变这个:

    if(diffX>=0 && diffX<4 && diffY>=0 && diffY<4){

对此:

    if(diffX>=0 && diffX<3 && diffY>=0 && diffY<3){

第三,你的findRow函数也超出了拼图界限。 将所有4改为3

第四,只有在你移动后才能检查你的胜利状态。 所以在交换下面移动你的胜利检查:

temp=arr[r][c];
arr[r][c]=arr[row][col];
arr[row][col]=temp;
// This victory check is now below the move.
if(n>=9){
    print();
    if(isReady())
        printf("Finished");
    depth++;

    return;
}

第五,你应该改变你的初始电话:

perm(0,0,0);

对此:

perm(1,1,0);

你拥有它的方式,你总是强行向左上方移动作为你的第一步。 修改后的方式将0保持在中心位置,因此不会强制您第一次移动。 当我使用我所做的所有修改运行此代码时,它找到了3个解决方案。 当我进一步修改代码以检查任何深度的解时,它在深度8找到2个解,在深度9找到3个解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM