hdu 1043(八數碼問題)

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章