hdu 1043(八数码问题)

来源:互联网 发布:淘宝 开电玩店 编辑:程序博客网 时间:2024/05/16 09:10

<span style="font-family: Arial, Helvetica, sans-serif;">题意:省略</span>

 解题思路:针对八数码问题,如果x往左或往右走,是不会改变逆序数大小的,且往上或往下走只有三种情况,讨论往下走,如果与x交换的数是ai,则要判断的是a(i-1),a(i-2)与ai的关系.

                 只会出现四种情况,a(i-1)>ai,a(i-2)>ai;逆序对数在原来的基础上+2

 a(i-1)<ai,a(i-2)>ai;逆序对数在原来的基础上不变

                                                 a(i-1)>ai,a(i-2)<ai;逆序对数在原来的基础上不变

 a(i-1)<ai,a(i-2)<ai;逆序对数在原来的基础上-2

 针对上述四种情况,逆序数的初始值为0,则经过各种变换逆序数为偶数,则若一种状态逆序数为奇数,始不可能的。且在保存状态时利用康托展开:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! (ai为某个数对应的逆序对数,达到状态压缩)。

 这里要利用反向的思维,通过最终状态去bfs所有状态。          




                 只会出现四种情况,a(i-1)>ai,a(i-2)>ai;逆序对数在原来的基础上+2

 a(i-1)<ai,a(i-2)>ai;逆序对数在原来的基础上不变

                                                 a(i-1)>ai,a(i-2)<ai;逆序对数在原来的基础上不变

 a(i-1)<ai,a(i-2)<ai;逆序对数在原来的基础上-2

 针对上述四种情况,逆序数的初始值为0,则经过各种变换逆序数为偶数,则若一种状态逆序数为奇数,始不可能的。且在保存状态时利用康托展开:X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! (ai为某个数对应的逆序对数,达到状态压缩)。

 这里要利用反向的思维,通过最终状态去bfs所有状态。

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <queue>using namespace std;#define MAXN 50#define MAZE 600000typedef struct node{    char str[50];    int nx[9];    int num,hashnum,xind;    node();    node(char *ss,int nu,int hanu,int *nnx){        strcpy(str,ss);        num = nu;        hashnum = hanu;        for(int i=0;i<9;++i){            nx[i] = nnx[i];        }    }    void charstr(){        int tmp = 0;        int tmpc;        int tmpnum = num;        tmpc = 9;        int zflag = 0;        while(num){            zflag = num%10;            str[tmpc -1] = '0'+ zflag;            if(zflag==9)                tmp = tmpc - 1;            num/=10;            --tmpc;        }        num = tmpnum;        xind = tmp;        //return tmp;    }};queue<node>q;int path[MAZE];int nx[9];int pa[MAZE],ans[MAZE];bool vis[MAZE];char nows[MAXN];int cnt;int p[]={1,1,2,6,24,120,720,5040,40320};int pw[] = {100000000,10000000,1000000,100000,10000,1000,100,10,1};int dx[] = {0,0,1,-1};int dy[] = {1,-1,0,0};int goal;void prepro(){    cnt = 0;    int len = (int)strlen(nows);    for(int i=0;i<len;++i){        if(nows[i]==32)continue;        if(nows[i]=='x')nows[i] = '9';        nows[cnt++] = nows[i];    }    nows[cnt] = 0;}void init(){    memset(vis,false,sizeof(vis));    memset(pa,-1,sizeof(pa));}int charhash(char *str){    //就保证系数ai》=0&&ai<=(8 - i)    int ans = 0,tmpc;    int st = 0;    for(int i=0;i<cnt;++i){        //if(nows[i]=='x')continue;        tmpc = 0;        for(int j = i+1;j<cnt;++j){            //  if(nows[j]=='x')continue;            if(str[i]>str[j])tmpc++;        }        nx[i] = tmpc;        ans+=tmpc*p[8-i];        //st++;    }    return ans;}int getnx(){    int ans = 0;    for(int i=0;i<cnt;++i){        //if(nows[i]=='x')continue;        if(nows[i]=='9')continue;        for(int j=i+1;j<cnt;++j){            // if(nows[j]=='x')continue;            if(nows[i]>nows[j])                ans++;        }    }    return ans;}int getnumber(){    int   ans = 123456789;    return ans;}//右 左 下 上int gethash(char *str,int num,int dir,int xind,int nxind,node &no){    int tmpcc;    if(dir==0){                num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind];        tmpcc = no.nx[nxind];        no.nx[nxind]=no.nx[xind] - 1;        no.nx[xind] = tmpcc;        num+=p[8-xind]*no.nx[xind]  + p[8-nxind]*no.nx[nxind];    }    if(dir==1){        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind];        tmpcc = no.nx[nxind];        no.nx[nxind]=no.nx[xind] + 1;        no.nx[xind] = tmpcc;        num+=p[8-xind]*no.nx[xind]  + p[8-nxind]*no.nx[nxind];    }        if(dir==2){        int ind1,ind2;        ind1 = xind+1;        ind2 = xind+2;        int cc = 0;        if(str[nxind]>str[ind1])cc++;        if(str[nxind]>str[ind2])cc++;        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind];        tmpcc = no.nx[nxind];        no.nx[nxind]=no.nx[xind] - 3;        no.nx[xind] = tmpcc+cc;        num+=p[8-xind]*no.nx[xind]  + p[8-nxind]*no.nx[nxind];        if(str[nxind]<str[ind1]){            num-=p[8-ind1];            no.nx[ind1]--;        }        if(str[nxind]<str[ind2]){            num-=p[8-ind2];            no.nx[ind2]--;        }    }    if(dir==3){        int ind1,ind2;        ind1 = xind-1;        ind2 = xind-2;        int cc = 0;        if(str[nxind]>str[ind1])cc++;        if(str[nxind]>str[ind2])cc++;        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind];        tmpcc = no.nx[nxind];        no.nx[nxind]=no.nx[xind] + 3;        no.nx[xind] = tmpcc-cc;        num+=p[8-xind]*no.nx[xind]  + p[8-nxind]*no.nx[nxind];        if(str[nxind]<str[ind1]){            num+=p[8-ind1];            no.nx[ind1]++;        }        if(str[nxind]<str[ind2]){            num+=p[8-ind2];            no.nx[ind2]++;        }            }    return num;}//右 左 下 上void restart(char *str,int num,int dir,int xind,int nxind,node &no){    int tmpcc;    if(dir==0){        //        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]-1)  + p[8-nxind]*no.nx[xind];        tmpcc = no.nx[xind];        no.nx[xind]=no.nx[nxind] + 1;        no.nx[nxind] = tmpcc;    }    if(dir==1){        //        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]+1)  + p[8-nxind]*no.nx[xind];        tmpcc = no.nx[xind];        no.nx[xind]=no.nx[nxind] - 1;        no.nx[nxind] = tmpcc;            }        if(dir==2){        int ind1,ind2;        ind1 = xind+1;        ind2 = xind+2;        int cc = 0;        if(str[nxind]>str[ind1])cc++;        if(str[nxind]>str[ind2])cc++;        //        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]-2)  + p[8-nxind]*(no.nx[xind]+cc);        tmpcc = no.nx[xind];        no.nx[xind]=no.nx[nxind] + 3;        no.nx[nxind] = tmpcc-cc;        if(str[nxind]<str[ind1]){            // num+=p[8-ind1];            no.nx[ind1]++;        }        if(str[nxind]<str[ind2]){            //num+=p[8-ind2];            no.nx[ind2]++;        }    }    if(dir==3){        //        num = num-p[8-xind]*no.nx[xind]  - p[8-nxind]*no.nx[nxind] + p[8-xind]*(no.nx[nxind]+2)  + p[8-nxind]*(no.nx[xind]-cc);        int ind1,ind2;        ind1 = xind-1;        ind2 = xind-2;        int cc = 0;        if(str[nxind]>str[ind1])cc++;        if(str[nxind]>str[ind2])cc++;        tmpcc = no.nx[xind];        no.nx[xind]=no.nx[nxind] - 3;        no.nx[nxind] = tmpcc+cc;        if(str[nxind]<str[ind1]){            //num-=p[8-ind1];            no.nx[ind1]--;        }        if(str[nxind]<str[ind2]){            //num=p[8-ind2];            no.nx[ind2]--;        }    }    //    return num;}void solve(){    //int front,rear;    //    if(getnx()&1)    //        return false;    int num = getnumber();    int hashnum;    hashnum = charhash("123456789");    node no("123456789",num,hashnum,nx);    no.charstr();    q.push(no);    //vis[num] = true;    int tmpnum,xind,nxind;    int x,y,nx,ny;    while(!q.empty()){        no = q.front();        q.pop();        //  num = no.num;        //if(goal==no.hashnum)return true;        xind = no.xind;        if(vis[no.hashnum])continue;        vis[no.hashnum] = true;        //xind = charstr(num);        x = xind/3;        y = xind%3;        for(int i=0;i<4;++i){//右 左 下 上            nx = x + dx[i];            ny = y + dy[i];            if(nx>=0&&nx<3&&ny>=0&&ny<3){                nxind = nx*3+ny;                tmpnum = gethash(no.str,no.hashnum,i,xind,nxind,no);                int cc = no.str[nxind] - '0';                no.str[xind] = no.str[nxind];                no.str[nxind] = '9';                // int chc = charhash(no.str);                int t1,t2;                //  t1 = no.num;                t2 = no.hashnum;                if(!vis[tmpnum]){                    pa[tmpnum] = no.hashnum;                    path[tmpnum] = i;                    //   int tmpcc = num +  (9 - cc)*(pw[nxind]-pw[xind]);                    //  no.num = tmpcc;                    no.hashnum = tmpnum;                    no.xind = nxind;                    q.push(no);                }                no.str[nxind] = no.str[xind];                no.str[xind] = '9';                // no.num = t1;                no.hashnum = t2;                no.xind = xind;                restart(no.str,no.hashnum,i,xind,nxind,no);            }        }    }    //   return false;}int getdir(int num){    switch(num){        case 0: return 'l';        case 1: return 'r';        case 2: return 'u';        case 3: return 'd';    }    return  0;}void output(bool flag,int hashnum){    if(!flag){        printf("unsolvable\n");        return;    }    int cntans = 0;    int tmp = hashnum;    //char ss[]="ullddrurdllurdruldr";    //printf("%d\n",strlen(ss));    while(1){        if(pa[tmp]==-1)break;        ans[cntans++] = path[tmp];        tmp = pa[tmp];            }    //printf("%d",ans[0]);    // printf("%d\n",cntans);    for(int i=0;i<cntans;++i){        putchar(getdir(ans[i]));    }    printf("\n");}void clear(){    while(!q.empty()){        q.pop();    }}int main(){    init();    goal = 0;    solve();    //clear();    bool flag;    while(gets(nows)){        flag = true;        prepro();        int hashnum = charhash(nows);        if(!vis[hashnum])flag = false;        output(flag,hashnum);    }    return 0;}


0 0
原创粉丝点击