【A*/Meet in the middle/BFS模板】8数码问题

A*

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<stack>
using namespace std;
stack<char>s;
struct node{
    int dist,h,c;
    unsigned short s[10];
    bool operator<(const node &tt)const
    {
        return h+dist>tt.h+tt.dist;
    }
};
int stc,fact[10],f[362880+10],e,pre[362880+10];
unsigned short ppos[10][2]={{},{1,1},{1,2},{1,3},{2,1},{2,2},{2,3},{3,1},{3,2},{3,3}},st[10],goal[10]={0,1,2,3,4,5,6,7,8,0},dir[4][4]={{-1,0},{1,0},{0,-1},{0,1}};
unsigned short ffpos[4][4]={
    {},
    {0,1,2,3},
    {0,4,5,6},
    {0,7,8,9}               };
char dd[4]={'u','d','l','r'},b[362880+10];
priority_queue<node>q;
int h(unsigned short *s){
    int ret=0,i;
    for(i=1;i<=9;i++){
        if(!s[i])
            continue;
        ret+=abs(ppos[s[i]][0]-ppos[i][0])+abs(ppos[s[i]][1]-ppos[i][1]);
    }
    return ret;
}
bool vis[362880+10];
void init_lookup_table(){
    fact[1]=1;
    for(int i=2;i<=9;i++)
        fact[i]=fact[i-1]*i;
}
int Cantor(unsigned short *s){
    int code=0,i,j;
    for(i=1;i<=9;i++){
        int cnt=0;
        for(j=i+1;j<=9;j++)
            if(s[j]<s[i])
                cnt++;
        code+=fact[9-i]*cnt;
    }
    return code;
}
void structure(int c){
    while(1){
        if(c==stc)
            break;
        s.push(b[c]);
        c=pre[c];
    }
    while(!s.empty()){
        putchar(s.top());
        s.pop();
    }
}
void bfs(){
    while(!q.empty()){
        node p=q.top(),t;
        q.pop();
        if(p.c==e){
            structure(e);
            puts("");
            return;
        }
        unsigned short x,y,z,d,tx,ty,tz;
        for(z=1;z<=9;z++)
            if(!p.s[z])
                break;
        x=ppos[z][0],y=ppos[z][1];
        for(d=0;d<4;d++){
            t=p;
            t.dist++;
            tx=x+dir[d][0],ty=y+dir[d][1],tz=ffpos[tx][ty];
            if(!tx||!ty||tx>3||ty>3)
                continue;
            t.s[tz]=p.s[z];
            t.s[z]=p.s[tz];
            t.c=Cantor(t.s);
            t.h=h(t.s);
            if(!f[t.c]){
                pre[t.c]=p.c;
                b[t.c]=dd[d];
                q.push(t);
                f[t.c]=t.dist+t.h;
            }
        }
    }
}
bool check(){
    int ca=0,cb=0,i,j;
    for(i=1;i<=9;i++)
        for(j=i+1;j<=9;j++){
            if(st[i]>st[j]&&st[j])
                ca++;
            if(goal[i]>goal[j]&&goal[j])
                cb++;
        }
    if((ca&1)==(cb&1))
        return 1;
    return 0;
}
int main()
{
    init_lookup_table();
    while(1){
        while(!q.empty())
            q.pop();
        memset(f,0,sizeof f);
        int i;
        char ch[10];
        for(i=1;i<=9;i++){
            if(scanf("%s",ch)==EOF)
                return 0;
            if(ch[0]=='x')
                st[i]=0;
            else 
                st[i]=ch[0]-'0';
        }
        if(!check()){
            puts("unsolvable");
            continue;
        }
        int c=Cantor(st);
        stc=c;
        e=Cantor(goal);
        int hh=h(st);
        f[c]=hh;
        node t;
        t.dist=0;
        t.h=hh;
        t.c=c;
        memcpy(t.s,st,sizeof st);
        q.push(t);
        bfs();
    }
}

Meet in the middle(不输出方案)

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int posx;
struct node
{
    char s[10];
    int hash;
    int id;
    int f;
    node(const char *a,const int &b,const int &d,const int &e){
        strcpy(s,a);
        id=b;
        f=d;
        hash=e;
    }
};
bool f[10],vis[2][370000];
int bv[10]={1,1,2,6,24,120,720,5040,40320},map[370000];
int order(char *t)
{
    int ans=0;
    for(int i=0;i<9;i++)
    {
        int tmp=0;
        for(int j=i+1;j<9;j++)
        {
            if(t[i]>t[j])
                tmp++;
        }
        ans+=tmp*bv[8-i];
    }
    return ans;
}
char a[10],b[10];
int dd[4]={-3,1,-1,3};
queue<node>q;
void BFS()
{
    while(!q.empty())
    {
        int pos=q.front().id,k=q.front().f,hash=q.front().hash;
        char*a=q.front().s;
        for(int i=0;i<4;i++)
            if(pos+dd[i]>=0&&pos+dd[i]<9&&(pos/3==(dd[i]+pos)/3||pos%3==(pos+dd[i])%3))
            {
                swap(a[pos],a[dd[i]+pos]);
                int num=order(a);
                if(!vis[k^1][num]&&!vis[k][num])
                {
                    q.push(node(a,dd[i]+pos,k,num));
                    vis[k][num]=1;
                    map[num]=map[hash]+1;
                }
                else if(vis[k^1][num])
                {
                    printf("%d\n",map[hash]+map[num]+1);
                    return;
                }
                swap(a[pos],a[dd[i]+pos]);
            }
        q.pop();
    }
}
int main()
{
    int t;
    for(int i=0;i<9;i++)
    {
        scanf("%d",&t);
        a[i]=t+'0';
        if(!t)posx=i;
    }
    int num=order(a);
    q.push(node(a,posx,0,num));
    vis[0][num]=1;
    for(int i=0;i<9;i++)
    {
        scanf("%d",&t);
        b[i]=t+'0';
        if(!t)posx=i;
    }
    num=order(b);
    q.push(node(b,posx,1,num));
    vis[1][num]=1;
    int cnt1,cnt2;
    cnt1=cnt2=0;
    for(int i=1;i<9;++i)
        for(int j=0;j<i;++j)
        {
            if(a[i]!='0'&&a[i]<a[j])cnt1++;
            if(b[i]!='0'&&b[i]<b[j])cnt2++;
        }
    if((cnt1^cnt2)&1){printf("-1");return 0;}
    BFS();
}

BFS

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<stack>
using namespace std;
stack<char>s;
struct node{
    int dist,c;
    int s[10];
};
int stc,fact[10],e,pre[362880+10];
int ppos[10][2]={{},{1,1},{1,2},{1,3},{2,1},{2,2},{2,3},{3,1},{3,2},{3,3}},st[10],goal[10]={0,1,2,3,4,5,6,7,8,0},dir[4][4]={{-1,0},{0,-1},{1,0},{0,1}};
int ffpos[4][4]={
    {},
    {0,1,2,3},
    {0,4,5,6},
    {0,7,8,9}               };
char dd[4]={'u','l','d','r'},b[362880+10];
queue<node>q;
bool vis[362880+10];
void init_lookup_table(){
    fact[1]=1;
    for(int i=2;i<=9;i++)
        fact[i]=fact[i-1]*i;
}
int Cantor(int *s){
    int code=0,i,j;
    for(i=1;i<=9;i++){
        int cnt=0;
        for(j=i+1;j<=9;j++)
            if(s[j]<s[i])
                cnt++;
        code+=fact[9-i]*cnt;
    }
    return code;
}
void structure(int c){
    while(1){
        if(c==stc)
            break;
        s.push(b[c]);
        c=pre[c];
    }
    while(!s.empty()){
        putchar(s.top());
        s.pop();
    }
}
void bfs(){
    while(!q.empty()){
        node p=q.front(),t;
        q.pop();
        if(p.c==e){
            structure(e);
            puts("");
            return;
        }
        int x,y,z,d,tx,ty,tz;
        for(z=1;z<=9;z++)
            if(!p.s[z])
                break;
        x=ppos[z][0],y=ppos[z][1];
        for(d=0;d<4;d++){
            t=p;
            t.dist++;
            tx=x+dir[d][0],ty=y+dir[d][1],tz=ffpos[tx][ty];
            if(!tx||!ty||tx>3||ty>3)
                continue;
            t.s[tz]=p.s[z];
            t.s[z]=p.s[tz];
            t.c=Cantor(t.s);
            if(!vis[t.c]){
                pre[t.c]=p.c;
                b[t.c]=dd[d];
                q.push(t);
                vis[t.c]=1;
            }
        }
    }
}
bool check(){
    int ca=0,cb=0,i,j;
    for(i=1;i<=9;i++)
        for(j=i+1;j<=9;j++){
            if(st[i]>st[j]&&st[j])
                ca++;
            if(goal[i]>goal[j]&&goal[j])
                cb++;
        }
    if((ca&1)==(cb&1))
        return 1;
    return 0;
}
int main()
{
    init_lookup_table();
    while(1){
        while(!q.empty())
            q.pop();
        memset(vis,0,sizeof vis);
        int i;
        char ch[10];
        for(i=1;i<=9;i++){
            if(scanf("%s",ch)==EOF)
                return 0;
            if(ch[0]=='x')
                st[i]=0;
            else 
                st[i]=ch[0]-'0';
        }
        if(!check()){
            puts("NO SOLUTION");
            continue;
        }
        int c=Cantor(st);
        stc=c;
        e=Cantor(goal);
        vis[c]=1;
        node t;
        t.dist=0;
        t.c=c;
        memcpy(t.s,st,sizeof st);
        q.push(t);
        bfs();
    }
}
posted @ 2016-01-30 09:56  outer_form  阅读(177)  评论(0编辑  收藏  举报