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;
}

 

posted @ 2013-12-08 14:18  紫忆  阅读(498)  评论(0编辑  收藏  举报