poj1077八数码问题——境界二

来源:互联网 发布:网站存在sql注入漏洞 编辑:程序博客网 时间:2024/05/29 10:06

八数码之八重境界http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html

关键在于利用康托展开判重

发现自己模拟的队列比STL中queue快

#include<stdio.h>#include<string.h>#include<string>#include<algorithm>#include<iostream>#include<set>#include<map>#include<queue>#include<stack>#include<vector>#include<math.h>#include<stdlib.h>#define M 400000using namespace std;struct stu{    char s[20];    int pos;}st,ed,dl[M];struct pa{    int fa;    char c;}path[M];int mark[M];int jc[12];int h[4]={-1,0,1,0};int z[4]={0,1,0,-1};char fa[]={"urdl"},pstr[M];void getjc()//阶乘 {    int i,j,k;    jc[0]=1;    for(i=1;i<12;i++)    jc[i]=jc[i-1]*i;}int getkt(char s[20])//康托展开 {    int i,j,k,len,an[20],ans=0;    getjc();    len=strlen(s);    memset(an,0,sizeof(an));    for(i=0;i<len;i++)//获得当前未出现的比他小的数,即它右边有几个比他小的数     for(j=0;j<i;j++)    {        if(s[j]>s[i])        an[j]++;    }    for(i=0;i<len;i++)//康托公式运算     {        ans+=an[i]*jc[len-i-1];    }       return ans;     }void prin(char s[20]){    int i,j;    for(i=0;i<9;i++)    {        if(i%3==0)        puts("");        printf("%c ",s[i]);    }}void getnikc(int len,int xu)//逆康托 {    int i,j,k;    int xs[20],js[20];    char s[20];    getjc();    for(i=len-1,j=0;i>=0;i--,j++)//辗转相除,得到an     {        xs[j]=xu/jc[i];        if(xu!=0)        xu=xu%jc[i];        js[i]=1;        }     for(i=0;i<len;i++)//找剩下子集中的第xs[i]大元素     {        int t=0;        for(j=0;j<len;j++)        {            t+=js[j];            if(t>xs[i])            {                s[i]='0'+j;                js[j]=0;                break;            }        }    }    s[len]='\0';    prin(s);}int judge(int x,int y){    return (x>=0&&x<3&&y>=0&&y<3);}int bfs(){    int i,j,k,r,f,x,y,t;    char s[20];    char c;    memset(mark,0,sizeof(mark));    r=f=0;    dl[0]=st;    k=getkt(st.s);    mark[k]=1;    path[k].fa=k;//  printf("st kt %d\n",k);    while(r<=f)    {        k=getkt(dl[r].s);        if(k==ed.pos)        return k;        for(i=0;i<4;i++)        {            stu nw;            strcpy(nw.s,dl[r].s);            int p=dl[r].pos;            x=p/3;            y=p%3;        //  printf("qian x=%d,y=%d %d\n",x,y,p);            x=x+h[i];            y=y+z[i];        //  printf("hou  x=%d,y=%d %d\n",x,y,x*3+y);            if(judge(x,y))            {                t=x*3+y;                c=nw.s[p];                nw.s[p]=nw.s[t];                nw.s[t]=c;                nw.pos=t;                               t=getkt(nw.s);                if(mark[t]==0)                {                    dl[++f]=nw;                    path[t].fa=k;                    path[t].c=fa[i];                    mark[t]=1;                }                           }        }        r++;            }    return -1;}int main(){//  freopen("1077.in","r",stdin); // freopen("1077.out","w",stdout);    int i,j,k;     char c;        for(i=0;i<9; )    {             scanf("%c",&c);        if(c == 'x')        {                 st.s[i]='0';               st.pos=i;               i++;        }                else if(c>='0'&&c<='9')            {            st.s[i] = c;             i++;        }               else        continue;                   }    st.s[9]='\0';//  printf("aaa  %s  %d\n",st.s,st.pos);//  while(1)    {/*        scanf("%s",st.s);        for(i=0;i<9;i++)        {            if(st.s[i]=='x')            {                st.pos=i;                st.s[i]='0';            }        }*/        strcpy(ed.s,"123456780");        ed.pos=getkt(ed.s);//      printf("ed.p %d\n",ed.pos);        int ans=bfs();        if(ans==-1)        {            puts("unsolvable");        }        else        {            i=0;        //  getnikc(9,ans);            while(ans!=path[ans].fa)            {            //  printf("\nans %d  fa %d\n",ans,path[ans].fa);        //      printf("%c",path[ans].c);                pstr[i++]=path[ans].c;                ans=path[ans].fa;            //  getnikc(9,ans);            }            pstr[i]='\0';        //  puts("");            reverse(pstr,pstr+i);            puts(pstr);        }    }    return 0;}/*23415x768*/