(中等) HDU 1043 Eight,经典搜索问题。

  Problem Description
  The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x

  where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->

  The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.

  Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

  In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.

 

  这前那篇文章也介绍了一些了,那位大神的文章也写的很好了,我就是来水一下。

 

  首先就是我写的康托展开,用来表示每一个状态,其实对于一个状态 2 3 4 1 5 x 7 6 8来说,把x当作0,就是0到8的一个全排了,那么一共就9!种,这样就是第一个*8!,第二个*7!。。。这样下去。。。不过每一个乘的数应该是这个数本身的值减去前面比他小的个数,也就是他在剩下的数里面是第几个。

  由一个值转化为一个排列也是如此,每一次找第k个还没有用到的数,就是那个数了。因为这里就只有9个数,直接n^2过一遍就好了。。。(对于很多数,可以用数状数组来做,转化为排列的话就是二分加数状数组。)

 

  然后是减枝,减去无解的情况。对于每一次移动,数的逆序对的奇偶性是不会改变的(这里x不算数),然后的话先求逆序数,如果为奇就直接pass掉。

 

首先是第一次写,

BFS+康托+剪枝,TLE了。

#include<iostream>
#include<cstring>

using namespace std;

const int maxn=400005;
const int Enum=46233;
const int jie[9]={1,1,2,6,24,120,720,5040,40320};

int que[400005];
int fa[maxn];
int las,fir;
int rem[maxn];
char ans1[maxn];
int cou;

int hebing(int (*m)[3])
{
    bool vis[10]={0};
    int cou;
    int ans=0;

    for(int i=0;i<9;++i)
    {
        cou=0;
        for(int j=0;j<m[i/3][i%3];++j)
            if(vis[j])
                ++cou;

        vis[m[i/3][i%3]]=1;

        ans+=(m[i/3][i%3]-cou)*jie[8-i];
    }

    return ans;
}

void zhankai(int (*m)[3],int x)
{
    bool vis[10]={0};
    int cou;
    int k;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
        {
            cou=x/jie[8-3*i-j]+1;        //    !!!
            x%=jie[8-3*i-j];
            
            for(k=0;k<9&&cou;++k)
                if(vis[k]==0)
                    --cou;

            vis[k-1]=1;                    //  !!!
            m[i][j]=k-1;                //  !!!
        }
}

void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

bool judge(int x,int y)
{
    if(x<0||y<0||x>2||y>2)
        return 0;

    return 1;
}

void showans()
{
    int temp=Enum;
    char c;
    cou=0;

    while(fa[temp]!=-1)
    {
        if(rem[temp]==1)
            c='d';
        else if(rem[temp]==2)
            c='l';
        else if(rem[temp]==3)
            c='u';
        else
            c='r';

        ans1[cou++]=c;

        temp=fa[temp];
    }

    for(int i=cou-1;i>=0;--i)
        cout<<ans1[i];

    cout<<endl;
}

void solve(int (*m)[3])
{
    int ni=0;

    for(int i=0;i<9;++i)
        for(int j=0;j<i;++j)
            if(m[i/3][i%3]&&m[j/3][j%3])
                if(m[i/3][i%3]<m[j/3][j%3])
                    ++ni;

    if(ni%2)
    {
        cout<<"unsolvable\n";
        return;
    }

    las=fir=0;
    memset(rem,0,sizeof(rem));

    bool ok=0;
    int temp,t1[3][3],temp1;
    int x0,y0;

    temp=hebing(m);

    rem[temp]=-1;
    que[las++]=temp;
    fa[temp]=-1;

    while(las-fir)
    {
        temp=que[fir++];

        if(temp==Enum)
        {
            ok=1;
            break;
        }

        zhankai(t1,temp);

        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
                if(t1[i][j]==0)
                    x0=i,y0=j;

        if(judge(x0-1,y0))
        {
            swap(t1[x0][y0],t1[x0-1][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                rem[temp1]=3;
                fa[temp1]=temp;
                que[las++]=temp1;
            }

            swap(t1[x0][y0],t1[x0-1][y0]);
        }
        if(judge(x0+1,y0))
        {
            swap(t1[x0+1][y0],t1[x0][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                rem[temp1]=1;
                fa[temp1]=temp;
                que[las++]=temp1;
            }

            swap(t1[x0][y0],t1[x0+1][y0]);
        }
        if(judge(x0,y0-1))
        {
            swap(t1[x0][y0-1],t1[x0][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                rem[temp1]=2;
                fa[temp1]=temp;
                que[las++]=temp1;
            }

            swap(t1[x0][y0],t1[x0][y0-1]);
        }
        if(judge(x0,y0+1))
        {
            swap(t1[x0][y0+1],t1[x0][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                rem[temp1]=4;
                fa[temp1]=temp;
                que[las++]=temp1;
            }

            swap(t1[x0][y0],t1[x0][y0+1]);
        }
    }

    if(ok)
        showans();
    else
        cout<<"unsolvable"<<endl;
}

int main()
{
    ios::sync_with_stdio(false);

    int m[3][3];
    char c;

    while(cin>>c)
    {
        m[0][0]=c=='x'?0:c-'0';
        cin>>c;
        m[0][1]=c=='x'?0:c-'0';
        cin>>c;
        m[0][2]=c=='x'?0:c-'0';

        for(int i=1;i<3;++i)
            for(int j=0;j<3;++j)
            {
                cin>>c;
                m[i][j]=c=='x'?0:c-'0';
            }

        solve(m);
    }

    return 0;
}
View Code

 

然后就是

双向BFS+康托+剪枝,就过了。

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int maxn=400005;
const int Enum=46233;
const int jie[9]={1,1,2,6,24,120,720,5040,40320};
const int step[4][2]={{1,0},{0,-1},{-1,0},{0,1}};

int Snum,Mnum;
int fa[maxn],son[maxn];
int rem[maxn],Mrem;
int que1[maxn],que2[maxn];
int las1,las2,fir1,fir2;
char ans[maxn];

int hebing(int (*m)[3])
{
    bool vis[10]={0};
    int cou;
    int ans=0;

    for(int i=0;i<9;++i)
    {
        cou=0;
        for(int j=0;j<m[i/3][i%3];++j)
            if(vis[j])
                ++cou;

        vis[m[i/3][i%3]]=1;

        ans+=(m[i/3][i%3]-cou)*jie[8-i];
    }

    return ans;
}

void zhankai(int (*m)[3],int x)
{
    bool vis[10]={0};
    int cou;
    int k;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
        {
            cou=x/jie[8-3*i-j]+1;        //    !!!
            x%=jie[8-3*i-j];
            
            for(k=0;k<9&&cou;++k)
                if(vis[k]==0)
                    --cou;

            vis[k-1]=1;                    //  !!!
            m[i][j]=k-1;                //  !!!
        }
}

void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

bool judge(int x,int y)
{
    if(x<0||y<0||x>2||y>2)
        return 0;

    return 1;
}

void showans()
{
    int cou=0;
    char c;
    int tnum=Mnum;

    while(tnum!=Snum)
    {
        if(rem[tnum]==1)
            c='d';
        else if(rem[tnum]==2)
            c='l';
        else if(rem[tnum]==3)
            c='u';
        else
            c='r';

        ans[cou++]=c;

        tnum=fa[tnum];
    }

    for(int i=cou-1;i>=0;--i)
        cout<<ans[i];

    rem[Mnum]=Mrem;
    tnum=Mnum;

    while(tnum!=Enum)
    {
        rem[tnum]=-rem[tnum];
        if(rem[tnum]==1)
            c='u';
        else if(rem[tnum]==2)
            c='r';
        else if(rem[tnum]==3)
            c='d';
        else
            c='l';

        cout<<c;

        tnum=son[tnum];
    }

    cout<<endl;
}

bool bfs()
{
    fir1=fir2=las1=las2=0;

    int temp,t1[3][3],t2[3][3];
    int tnum1,tnum2;
    int x01,y01,x02,y02;

    que1[las1++]=Snum;
    que2[las2++]=Enum;

    rem[Snum]=100;
    rem[Enum]=-100;

    son[Enum]=Enum;
    fa[Snum]=Snum;

    while(las1-fir1&&las2-fir2)
    {
        tnum1=que1[fir1++];
        tnum2=que2[fir2++];

        zhankai(t1,tnum1);
        zhankai(t2,tnum2);

        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
            {
                if(t1[i][j]==0)
                    x01=i,y01=j;
                if(t2[i][j]==0)
                    x02=i,y02=j;
            }

        for(int i=0;i<4;++i)
        {
            if(judge(x01+step[i][0],y01+step[i][1])==0)
                continue;
            
            swap(t1[x01][y01],t1[x01+step[i][0]][y01+step[i][1]]);
            temp=hebing(t1);

            if(rem[temp]==0)
            {
                rem[temp]=i+1;
                fa[temp]=tnum1;
                que1[las1++]=temp;
            }
            else if(rem[temp]<0)
            {
                fa[temp]=tnum1;
                Mrem=rem[temp];
                rem[temp]=i+1;
                Mnum=temp;

                return 1;
            }

            swap(t1[x01][y01],t1[x01+step[i][0]][y01+step[i][1]]);
        }

        for(int i=0;i<4;++i)
        {
            if(judge(x02+step[i][0],y02+step[i][1])==0)
                continue;

            swap(t2[x02][y02],t2[x02+step[i][0]][y02+step[i][1]]);
            temp=hebing(t2);

            if(rem[temp]==0)
            {
                rem[temp]=-(i+1);
                son[temp]=tnum2;
                que2[las2++]=temp;
            }
            else if(rem[temp]>0)
            {
                son[temp]=tnum2;
                Mrem=-(i+1);
                Mnum=temp;

                return 1;
            }

            swap(t2[x02][y02],t2[x02+step[i][0]][y02+step[i][1]]);
        }
    }

    return 0;
}

void solve(int (*m)[3])
{
    int ni=0;

    for(int i=0;i<9;++i)
        for(int j=0;j<i;++j)
            if(m[i/3][i%3]&&m[j/3][j%3])
                if(m[i/3][i%3]<m[j/3][j%3])
                    ++ni;

    if(ni%2)
    {
        cout<<"unsolvable\n";
        return;
    }

    memset(rem,0,sizeof(rem));

    Snum=hebing(m);

    if(Snum==Enum)
    {
        cout<<endl;
        return;
    }

    if(bfs())
        showans();
    else
        cout<<"unsolvable\n";
}

int main()
{
    ios::sync_with_stdio(false);

    int m[3][3];
    char c;

    while(cin>>c)
    {
        m[0][0]=c=='x'?0:c-'0';
        cin>>c;
        m[0][1]=c=='x'?0:c-'0';
        cin>>c;
        m[0][2]=c=='x'?0:c-'0';

        for(int i=1;i<3;++i)
            for(int j=0;j<3;++j)
            {
                cin>>c;
                m[i][j]=c=='x'?0:c-'0';
            }

        solve(m);
    }

    return 0;
}
View Code

 

A*(曼哈顿距离)+康托+剪枝。

#include<iostream>
#include<cstring>
#include<queue>
#include<utility>
#include<cmath>
#include<cstdio>

using namespace std;

const int maxn=400005;
const int Enum=46233;
const int jie[9]={1,1,2,6,24,120,720,5040,40320};

struct state
{
    int F,G,num;

    state() {}
    state(int a,int b,int c):F(a),G(b),num(c) {}

    friend bool operator < (state x,state y)
    {
        return x.F>y.F;
    }
};

int fa[maxn];
int rem[maxn];
char ans1[maxn];
int cou;

int hebing(int (*m)[3])
{
    bool vis[10]={0};
    int cou;
    int ans=0;

    for(int i=0;i<9;++i)
    {
        cou=0;
        for(int j=0;j<m[i/3][i%3];++j)
            if(vis[j])
                ++cou;

        vis[m[i/3][i%3]]=1;

        ans+=(m[i/3][i%3]-cou)*jie[8-i];
    }

    return ans;
}

void zhankai(int (*m)[3],int x)
{
    bool vis[10]={0};
    int cou;
    int k;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
        {
            cou=x/jie[8-3*i-j]+1;        //    !!!
            x%=jie[8-3*i-j];
            
            for(k=0;k<9&&cou;++k)
                if(vis[k]==0)
                    --cou;

            vis[k-1]=1;                    //  !!!
            m[i][j]=k-1;                //  !!!
        }
}

void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

bool judge(int x,int y)
{
    if(x<0||y<0||x>2||y>2)
        return 0;

    return 1;
}

void showans()
{
    int temp=Enum;
    char c;
    cou=0;

    while(fa[temp]!=-1)
    {
        if(rem[temp]==1)
            c='d';
        else if(rem[temp]==2)
            c='l';
        else if(rem[temp]==3)
            c='u';
        else
            c='r';

        ans1[cou++]=c;

        temp=fa[temp];
    }

    for(int i=cou-1;i>=0;--i)
        cout<<ans1[i];

    cout<<endl;
}

int getH(int (*m)[3])
{
    int H=0;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
            if(m[i][j])
                H+=abs(i-(m[i][j]-1)/3)+abs(j-(m[i][j]-1)%3);
            else
                H+=abs(i-2)+abs(j-2);

    return H;
}

void solve(int (*m)[3])
{
    int ni=0;

    for(int i=0;i<9;++i)
        for(int j=0;j<i;++j)
            if(m[i/3][i%3]&&m[j/3][j%3])
                if(m[i/3][i%3]<m[j/3][j%3])
                    ++ni;

    if(ni%2)
    {
        cout<<"unsolvable\n";
        return;
    }

    priority_queue <state> que;

    memset(rem,0,sizeof(rem));

    bool ok=0;
    int temp,t1[3][3],temp1;
    int x0,y0;
    int H=0,G;
    state tsta;

    temp=hebing(m);

    que.push(state(H,0,temp));
    rem[temp]=-1;
    fa[temp]=-1;

    while(!que.empty())
    {
        H=0;

        tsta=que.top();
        que.pop();

        G=tsta.G;
        temp=tsta.num;

        if(temp==Enum)
        {
            ok=1;
            break;
        }

        zhankai(t1,temp);

        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
                if(t1[i][j]==0)
                    x0=i,y0=j;

        if(judge(x0-1,y0))
        {
            swap(t1[x0][y0],t1[x0-1][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                H=getH(t1);
                rem[temp1]=3;
                fa[temp1]=temp;
                que.push(state(G+1+H,G+1,temp1));
            }

            swap(t1[x0][y0],t1[x0-1][y0]);
        }
        if(judge(x0+1,y0))
        {
            swap(t1[x0+1][y0],t1[x0][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                H=getH(t1);
                rem[temp1]=1;
                fa[temp1]=temp;
                que.push(state(G+H+1,G+1,temp1));
            }

            swap(t1[x0][y0],t1[x0+1][y0]);
        }
        if(judge(x0,y0-1))
        {
            swap(t1[x0][y0-1],t1[x0][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                H=getH(t1);
                rem[temp1]=2;
                fa[temp1]=temp;
                que.push(state(G+H+1,G+1,temp1));
            }

            swap(t1[x0][y0],t1[x0][y0-1]);
        }
        if(judge(x0,y0+1))
        {
            swap(t1[x0][y0+1],t1[x0][y0]);
            temp1=hebing(t1);

            if(rem[temp1]==0)
            {
                H=getH(t1);
                rem[temp1]=4;
                fa[temp1]=temp;
                que.push(state(G+H+1,G+1,temp1));
            }

            swap(t1[x0][y0],t1[x0][y0+1]);
        }
    }

    if(ok)
        showans();
    else
        cout<<"unsolvable"<<endl;
}

int main()
{
    ios::sync_with_stdio(false);

    int m[3][3];
    char c;

    while(cin>>c)
    {
        m[0][0]=c=='x'?0:c-'0';
        cin>>c;
        m[0][1]=c=='x'?0:c-'0';
        cin>>c;
        m[0][2]=c=='x'?0:c-'0';

        for(int i=1;i<3;++i)
            for(int j=0;j<3;++j)
            {
                cin>>c;
                m[i][j]=c=='x'?0:c-'0';
            }

        solve(m);
    }

    return 0;
}
View Code

 

双向A*(曼哈顿距离)+康托+剪枝。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>

using namespace std;

const int maxn=400005;
const int Enum=46233;
const int jie[9]={1,1,2,6,24,120,720,5040,40320};
const int step[4][2]={{1,0},{0,-1},{-1,0},{0,1}};

struct state
{
    int F,G,num;

    state() {}
    state(int a,int b,int c):F(a),G(b),num(c) {}

    friend bool operator < (state x,state y)
    {
        return x.F>y.F;
    }
};

int Snum,Mnum;
int fa[maxn],son[maxn];
int rem[maxn],Mrem;
char ans[maxn];

int hebing(int (*m)[3])
{
    bool vis[10]={0};
    int cou;
    int ans=0;

    for(int i=0;i<9;++i)
    {
        cou=0;
        for(int j=0;j<m[i/3][i%3];++j)
            if(vis[j])
                ++cou;

        vis[m[i/3][i%3]]=1;

        ans+=(m[i/3][i%3]-cou)*jie[8-i];
    }

    return ans;
}

void zhankai(int (*m)[3],int x)
{
    bool vis[10]={0};
    int cou;
    int k;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
        {
            cou=x/jie[8-3*i-j]+1;        //    !!!
            x%=jie[8-3*i-j];
            
            for(k=0;k<9&&cou;++k)
                if(vis[k]==0)
                    --cou;

            vis[k-1]=1;                    //  !!!
            m[i][j]=k-1;                //  !!!
        }
}

void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

bool judge(int x,int y)
{
    if(x<0||y<0||x>2||y>2)
        return 0;

    return 1;
}

void showans()
{
    int cou=0;
    char c;
    int tnum=Mnum;

    while(tnum!=Snum)
    {
        if(rem[tnum]==1)
            c='d';
        else if(rem[tnum]==2)
            c='l';
        else if(rem[tnum]==3)
            c='u';
        else
            c='r';

        ans[cou++]=c;

        tnum=fa[tnum];
    }

    for(int i=cou-1;i>=0;--i)
        cout<<ans[i];

    rem[Mnum]=Mrem;
    tnum=Mnum;

    while(tnum!=Enum)
    {
        rem[tnum]=-rem[tnum];
        if(rem[tnum]==1)
            c='u';
        else if(rem[tnum]==2)
            c='r';
        else if(rem[tnum]==3)
            c='d';
        else
            c='l';

        cout<<c;

        tnum=son[tnum];
    }

    cout<<endl;
}

int getH(int (*m)[3])
{
    int H=0;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
            if(m[i][j])
                H+=abs(i-(m[i][j]-1)/3)+abs(j-(m[i][j]-1)%3);
            else
                H+=abs(i-2)+abs(j-2);

    return H;
}

bool bfs()
{
    priority_queue <state> que1,que2;

    int temp,t1[3][3],t2[3][3];
    int tnum1,tnum2;
    int x01,y01,x02,y02;

    state tsta1,tsta2;
    int H,G1,G2;

    que1.push(state(0,0,Snum));
    que2.push(state(0,0,Enum));

    rem[Snum]=100;
    rem[Enum]=-100;

    son[Enum]=Enum;
    fa[Snum]=Snum;

    while(!que1.empty()&&!que2.empty())
    {
        tsta1=que1.top();
        tsta2=que2.top();
        que1.pop();
        que2.pop();

        tnum1=tsta1.num;
        tnum2=tsta2.num;
        G1=tsta1.G;
        G2=tsta2.G;

        zhankai(t1,tnum1);
        zhankai(t2,tnum2);

        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
            {
                if(t1[i][j]==0)
                    x01=i,y01=j;
                if(t2[i][j]==0)
                    x02=i,y02=j;
            }

        for(int i=0;i<4;++i)
        {
            if(judge(x01+step[i][0],y01+step[i][1])==0)
                continue;
            
            swap(t1[x01][y01],t1[x01+step[i][0]][y01+step[i][1]]);
            temp=hebing(t1);

            if(rem[temp]==0)
            {
                rem[temp]=i+1;
                fa[temp]=tnum1;
                H=getH(t1);
                que1.push(state(H+G1+1,G1+1,temp));
            }
            else if(rem[temp]<0)
            {
                fa[temp]=tnum1;
                Mrem=rem[temp];
                rem[temp]=i+1;
                Mnum=temp;

                return 1;
            }

            swap(t1[x01][y01],t1[x01+step[i][0]][y01+step[i][1]]);
        }

        for(int i=0;i<4;++i)
        {
            if(judge(x02+step[i][0],y02+step[i][1])==0)
                continue;

            swap(t2[x02][y02],t2[x02+step[i][0]][y02+step[i][1]]);
            temp=hebing(t2);

            if(rem[temp]==0)
            {
                rem[temp]=-(i+1);
                son[temp]=tnum2;
                H=getH(t2);
                que2.push(state(H+G2+1,G2+1,temp));
            }
            else if(rem[temp]>0)
            {
                son[temp]=tnum2;
                Mrem=-(i+1);
                Mnum=temp;

                return 1;
            }

            swap(t2[x02][y02],t2[x02+step[i][0]][y02+step[i][1]]);
        }
    }

    return 0;
}

bool JiOujian(int (*m)[3])
{
    int ni=0;

    for(int i=0;i<9;++i)
        for(int j=0;j<i;++j)
            if(m[i/3][i%3]&&m[j/3][j%3])
                if(m[i/3][i%3]<m[j/3][j%3])
                    ++ni;

    return ni%2;
}

void solve(int (*m)[3])
{
    if(JiOujian(m))
    {
        cout<<"unsolvable\n";
        return;
    }

    memset(rem,0,sizeof(rem));

    Snum=hebing(m);

    if(Snum==Enum)
    {
        cout<<endl;
        return;
    }

    if(bfs())
        showans();
    else
        cout<<"unsolvable\n";
}

int main()
{
    ios::sync_with_stdio(false);

    int m[3][3];
    char c;

    while(cin>>c)
    {
        m[0][0]=c=='x'?0:c-'0';
        cin>>c;
        m[0][1]=c=='x'?0:c-'0';
        cin>>c;
        m[0][2]=c=='x'?0:c-'0';

        for(int i=1;i<3;++i)
            for(int j=0;j<3;++j)
            {
                cin>>c;
                m[i][j]=c=='x'?0:c-'0';
            }

        solve(m);
    }

    return 0;
}
View Code

 

IDA*+剪枝。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

using namespace std;

const int maxn=400005;
const int Enum=46233;
const int jie[9]={1,1,2,6,24,120,720,5040,40320};
const int Step[4][2]={{1,0},{0,-1},{-1,0},{0,1}};

int ans[maxn];
int Deep;
int Node[3][3];
int x01,y01;

void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

bool judge()
{
    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
            if(Node[i][j]&&Node[i][j]!=i*3+j+1)
                return 0;

    return 1;
}

bool JiOujian()
{
    int ni=0;

    for(int i=0;i<9;++i)
        for(int j=0;j<i;++j)
            if(Node[i/3][i%3]&&Node[j/3][j%3])
                if(Node[i/3][i%3]<Node[j/3][j%3])
                    ++ni;

    return ni%2;
}

int getH()
{
    int reH=0;

    for(int i=0;i<3;++i)
        for(int j=0;j<3;++j)
            if(Node[i][j])
                reH+=abs(i-(Node[i][j]-1)/3)+abs(j-(Node[i][j]-1)%3);
            else
                reH+=abs(2-i)+abs(2-j);

    return reH;
}

void showans(int G)
{
    for(int i=0;i<G;++i)
        if(ans[i]==0)
            cout<<'d';
        else if(ans[i]==1)
            cout<<'l';
        else if(ans[i]==2)
            cout<<'u';
        else
            cout<<'r';

    cout<<endl;
}

bool judgeBian(int x,int y)
{
    if(x<0||y<0||x>2||y>2)
        return 0;

    return 1;
}

bool dfs(int G,int lasStep)
{
    int H=getH();

    if(H+G>Deep)
        return 0;

    if(judge())
    {
        showans(G);
        return 1;
    }

    for(int i=0;i<4;++i)
    {
        if(i%2==lasStep%2&&i!=lasStep)
            continue;

        if(judgeBian(x01+Step[i][0],y01+Step[i][1])==0)
            continue;

        swap(Node[x01][y01],Node[x01+Step[i][0]][y01+Step[i][1]]);
        x01+=Step[i][0];
        y01+=Step[i][1];

        ans[G]=i;

        if(dfs(G+1,i))
            return 1;

        x01-=Step[i][0];
        y01-=Step[i][1];
        swap(Node[x01][y01],Node[x01+Step[i][0]][y01+Step[i][1]]);
    }

    return 0;
}

void solve()
{
    if(JiOujian())
    {
        cout<<"unsolvable\n";
        return;
    }

    Deep=1;

    while(1)
    {
        if(dfs(0,-1))
            return;

        ++Deep;
    }
}

int main()
{
    ios::sync_with_stdio(false);

    char c;

    while(cin>>c)
    {
        Node[0][0]=c=='x'?0:c-'0';
        cin>>c;
        Node[0][1]=c=='x'?0:c-'0';
        cin>>c;
        Node[0][2]=c=='x'?0:c-'0';

        for(int i=1;i<3;++i)
            for(int j=0;j<3;++j)
            {
                cin>>c;
                Node[i][j]=c=='x'?0:c-'0';
            }

        for(int i=0;i<3;++i)
            for(int j=0;j<3;++j)
                if(Node[i][j]==0)
                    x01=i,y01=j;

        solve();
    }

    return 0;
}
View Code

 

posted @ 2015-01-17 17:43  WhyWhy。  阅读(253)  评论(0编辑  收藏  举报