Uestc-1490-Eight Puzzle

第一次做这种八数码的问题,本来以为要用A*等算法,但这个题后来发现只要做到状态压缩的话直接BFS似乎就已经足够了。

状态压缩采用了康托展开的方法(具体百度),然后在最开始预处理就先把所有的答案算出来,最后直接输出即可。

中间还有些地方可以优化~时间应该可以更快。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<iostream>
using namespace std;
int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
const int maxn=10e5+10;
struct node
{
    int num;
    int ans;
    int pos;

};
bool vis[maxn];
int ans[maxn];
int GetNum(const int *s) 
{
    int i, j, temp, num,len=9;
    num=0;
    for(i=0;i<len-1;i++)
    {
        temp=0;
        for(j=i+1;j<len;j++)
            if(s[j]<s[i])
                temp++;
        num+=fac[s[i]-1]*temp;
    }
    return num;
}
void GetNode(int num,int *str) {
    int n=9;
    int a[9]; 
    for(int i=2;i<=n;++i)
    {
        a[i-1]=num%i;
        num=num/i;
        str[i-1]=0;
    }
    str[0]=0;
    int rn, i;
    for(int k=n;k>=2;k--)
    {
        rn=0;
        for(i=n-1;i>=0;--i)
	{
            if(str[i]!=0)
                continue;
            if(rn==a[k-1])
                break;
            ++rn;
        }
        str[i]=k;
    }
    for(i=0;i<n;++i)
        if(str[i]==0)
	{
            str[i]=1;
            break;
        }
}
void BFS()
{
    queue<node> q;
    q.push((node){0,0,8});
    vis[0]=1;
    ans[0]=0;
    while(!q.empty())
    {
	node ita=q.front();
	int a[9],num,pos=ita.pos;
	q.pop();
	GetNode(ita.num,a);
	if(ita.pos/3>0)
	{
	    swap(a[pos],a[pos-3]);
	    num=GetNum(a);
	    if(!vis[num])
	    {
		q.push((node){num,ita.ans+1,pos-3});
		ans[num]=ita.ans+1;
		vis[num]=1;
	    }
	    swap(a[pos],a[pos-3]);
	}
	if(ita.pos/3<2)
	{
	    swap(a[pos],a[pos+3]);
	    num=GetNum(a);
	    if(!vis[num])
	    {
		q.push((node){num,ita.ans+1,pos+3});
		ans[num]=ita.ans+1;
		vis[num]=1;
	    }
	    swap(a[pos],a[pos+3]);
	}
	if(ita.pos%3>0)
	{
	    swap(a[pos],a[pos-1]);
	    num=GetNum(a);
	    if(!vis[num])
	    {
		q.push((node){num,ita.ans+1,pos-1});
		ans[num]=ita.ans+1;
		vis[num]=1;    
	    }
	    swap(a[pos],a[pos-1]);
	}
	if(ita.pos%3<2)
	{
	    swap(a[pos],a[pos+1]);
	    num=GetNum(a);
	    if(!vis[num])
	    {
		q.push((node){num,ita.ans+1,pos+1});
		ans[num]=ita.ans+1;
		vis[num]=1;
	    }
	    swap(a[pos],a[pos-1]);
	}
	
    }
}
int main()
{
    node start;
    char str[9][3];
    BFS();
    while(scanf("%s",str[0])!=EOF)
    {
	for(int i=1;i<9;i++)
	    scanf("%s",str[i]);
	int a[9];
	for(int i=0; i<9; ++i)
	{
	    if(str[i][0]=='x')
		a[i]=9;
	    else
		a[i]=str[i][0]-'0';
	}
	int num=GetNum(a);
	GetNode(0,a);
	if(!ans[num]&&num!=0)
	    printf("unsolvable\n");
	else
	    printf("%d\n",ans[num]);
    }
    return 0;
}



你可能感兴趣的:(bfs,状态压缩)