poj1077(康托展开+bfs+记忆路径)

题意:就是说,给出一个三行三列的数组,其中元素为1--8和x,例如:

1  2  3    现在,需要你把它变成:1  2  3      要的最少步数的移动方案。可以右移r,左移l,上移u,下移d
x 4 6 4 5 6
7 5 8 7 8 x

思路:这是赤裸裸的康托展开了吧?不知道康托展开的同学可以百度百科........好吧,其实我想说的是,这个题目怎么分析出,要用到康托展开的。首先,遇到这样的题目,元素比较少,又可以用到搜索,但是状态数比较多,也就是说,我需要找到一种方式来压缩这些状态,使得同一个状态不重复出现。额,说道这里,在不考虑时间、空间复杂度的情况下,的确可以直接开标记数组:vist[10][10][10][10][10][10][10][10][10],但是这样一来,会有许多重复的状态。有没有更好压缩状态的方法呢?是有的,进制压缩也是一种方法,只是对于这个题目不适用。那么还有康托展开,康托展开,可以使得这些状态压缩下来,只有9!个状态,如此就可以实现搜索了。

有的人说,广搜不能记录路径?这是错误的,广搜只要你清楚的记录这个状态的上个状态是什么,那么就可以记录路径,很明显只需要开个记录路径的搜索就ok了

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<queue>

using namespace std;

int t[10]= {1,1,2,6,24,120,720,5040,40320};

char ff[400000];

struct node

{

    char ch[10];

    int son;

    int wz;

};

struct node1        //记录路径

{

    char num;

    int father;

} s[362883];



int deal(char str[])       //康托展开

{

    int x[10],ans1=0;

    for(int i=0; i<9; i++)

        x[i]=str[i]-'0';



    /*for(int i=0;i<9;i++)

    printf("%d\t",x[i]);*/



    for(int i=0; i<9; i++)

    {

        int k=0;

        for(int j=i+1; j<9; j++)

            if(x[i]>x[j])

                k++;

        ans1+=k*t[8-i];

        //printf("%d  %d  %d\n",ans1,k,t[8-i]);

    }

    return ans1;

}



int flag=0;

void bfs(char str[])

{

    queue<node>q;

    node p;

    strcpy(p.ch,str);

    p.ch[9]='\0';

    p.son=deal(p.ch);

    // puts(p.ch);

    p.wz=8;

    //printf("%d\n",p.son);

    s[p.son].father=0;



    q.push(p);



    while(!q.empty())

    {

        //flag++;

        //printf("%d\n",flag);

        p=q.front();

        q.pop();

        int hang=p.wz/3;

        int lie=p.wz%3;

        {

            int x=hang-1;

            int y=lie;

            {

                int x=hang;

                int y=lie+1;

                if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)

                {

                    node p1;

                    strcpy(p1.ch,p.ch);

                    p1.wz=x*3+y;

                    char zf=p1.ch[p.wz];

                    p1.ch[p.wz]=p1.ch[p1.wz];

                    p1.ch[p1.wz]=zf;

                    p1.ch[9]='\0';

                    p1.son=deal(p1.ch);

                    if(s[p1.son].father==-1)

                    {

                        s[p1.son].father=p.son;

                        s[p1.son].num='l';

                        q.push(p1);

                    }

                }

            }



            {

                int x=hang;

                int y=lie-1;

                if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)

                {

                    node p1;

                    strcpy(p1.ch,p.ch);

                    p1.wz=x*3+y;

                    char zf=p1.ch[p.wz];

                    p1.ch[p.wz]=p1.ch[p1.wz];

                    p1.ch[p1.wz]=zf;

                    p1.ch[9]='\0';

                    p1.son=deal(p1.ch);

                    if(s[p1.son].father==-1)

                    {

                        s[p1.son].father=p.son;

                        s[p1.son].num='r';

                        q.push(p1);

                    }

                }

            }

            if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)

            {

                node p1;

                strcpy(p1.ch,p.ch);

                p1.wz=x*3+y;

                char zf=p1.ch[p.wz];

                p1.ch[p.wz]=p1.ch[p1.wz];

                p1.ch[p1.wz]=zf;

                p1.ch[9]='\0';

                p1.son=deal(p1.ch);

                if(s[p1.son].father==-1)

                {

                    s[p1.son].father=p.son;

                    s[p1.son].num='d';

                    q.push(p1);

                }

            }

        }



        {

            int x=hang+1;

            int y=lie;

            if(x>=0&&x<3&&y>=0&&y<3&&(x*3+y)<=8)

            {

                node p1;

                strcpy(p1.ch,p.ch);

                p1.wz=x*3+y;

                char zf=p1.ch[p.wz];

                p1.ch[p.wz]=p1.ch[p1.wz];

                p1.ch[p1.wz]=zf;

                p1.ch[9]='\0';

                p1.son=deal(p1.ch);

                if(s[p1.son].father==-1)

                {

                    s[p1.son].father=p.son;

                    s[p1.son].num='u';

                    q.push(p1);

                }

            }

        }





    }

}

int main()

{

    char str[10]= {'1','2','3','4','5','6','7','8','0'};

    for(int i=0; i<362883; i++)

    {

        s[i].father=-1;

    }

    //printf("%d\n",flag);

    bfs(str);

    char ss[10][10];

    char tt[10];

    scanf("%s",ss[0]);

    {

        if(ss[0][0]!='x')

            tt[0]=ss[0][0];

        else

            tt[0]='0';      //把x转化为数字0

        for(int i=1; i<9; i++)

        {

            scanf("%s",ss[i]);

            if(ss[i][0]!='x')

                tt[i]=ss[i][0];

            else

                tt[i]='0';

        }

        tt[9]='\0';

        //puts(tt);

        int ans=deal(tt);

        int cnt=0;

        flag=0;

        while(ans!=0)        //回溯路径

        {

            ff[cnt++]=s[ans].num;

            ans=s[ans].father;

            if(ans==-1)

            {

                flag=1;

                break;

            }

        }

        int i=0;

        if(flag==0)

        {

            while(cnt>i)

                printf("%c",ff[i++]);

        }

        else   printf("unsolvable");

        printf("\n");

    }

    return 0;

}

 

你可能感兴趣的:(poj)