[POJ]1077 Eight 八数码:康托展开+BFS

嗯~很久以前没敲过的题,当时不懂状态压缩,不懂A*。因而没过...

现在用的康托展开+普通的BFS还是过了360ms也算是一个进步吧~

A*现在还是没有勇气去写... 加油!时间给我的不多了!~

(用C++TLE了... 改为G++就过了...)

Code:

#include<stdio.h>
#include<queue>
using namespace std;

struct node
{
 	   int eight[9];
}S,E;
int fec[10]={1,1,2,6,24,120,720,5040,40320,362880 };
 
void init()
{
 	char s;
 	int i=0;
 	while( scanf("%c",&s)!=EOF )
 	{
	 	   if( s!=' ' )
  	   	   {
		   	   if( s=='x' )
		   	   	   S.eight[i++]=9;
		   	   else
		   	   	   S.eight[i++]=s-'0';
	   	   }
    }
	for( i=0;i<9;i++ )
		 E.eight[i]=i+1;
}

int nodeToNum( node a )
{
 	int ret=0;
 	for( int i=0;i<9;i++ )
 		 ret=ret*10+a.eight[i];
	return ret;
}

int cantor( node a )
{
 	int ret=0;
 	bool flag[10]={false};
 	
 	for( int i=0;i<9;i++ )
 	{
	 	 int k=a.eight[i];
	 	 flag[k]=true;
	 	 int p=0;
	 	 for( int j=1;j<k;j++ )
	 	 	  if( flag[j]==false )
	 	 	  	  p++;
 	  	 ret+=p*fec[8-i];
	}
	return ret;
}

char select[400000];
char item[5]={ ' ','u','r','d','l' };
int pre[400000];
bool hash[400000]={false};

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

node work( node a,int n )
{
 	 int index;
 	 for( int i=0;i<9;i++ )
	  	  if( a.eight[i]==9 )
	  	  	  index=i;
 	 if( n==1 )
 	 {
	     if( index-3>=0 )
  	     	 swap( a.eight[index],a.eight[index-3] );
	 }
	 else if( n==2 )
	 {
	  	 if( index%3!=2 )
	  	 	 swap( a.eight[index],a.eight[index+1] );
	 }
	 else if( n==3 )
	 {
	  	  if( index+3<9 )
  	     	 swap( a.eight[index],a.eight[index+3] ); 	  
     }
     else if( n==4 )
     {
	  	  if( index%3!=0 )
	     	 swap( a.eight[index],a.eight[index-1] );
  	 }
  	 return a;
}

void print( int at )
{
 	 char cans[40000];
 	 int len=0;
 	 for( int i=at;pre[i]!=-1;i=pre[i] )
 	 	  cans[len++]=select[i];
	 for( int i=len-1;i>=0;i-- )
	 	  printf( "%c",cans[i] );
     printf( "\n" );
}

void bfs()
{
 	 queue<node> Q;
 	 Q.push(S);
 	 int head=0;
 	 int foot=1;
 	 pre[0]=-1;
 	 hash[cantor(S)]=true;
 	 if( nodeToNum(S)==nodeToNum(E) )
 	 {	 
	 	 printf( "\n" );
 	 	 return ;
     }
     while( !Q.empty() )
     {
	  		node cur=Q.front();
	  		Q.pop();
	  		node temp;
	  		for( int i=1;i<=4;i++ )
	  		{
	  			 temp=work( cur,i );
	  			 int ans=cantor(temp);
	  			 if( hash[ans]==false )
	  			 {
	  			 	 hash[ans]=true;
	  			 	 pre[foot]=head;
	  			 	 select[foot]=item[i];
	  			 	 foot++;
	  			 	 Q.push(temp);
				 	 if( nodeToNum(temp)==nodeToNum(E) )
		 		 	 {
				  	  	 print( foot-1 );
				  	 	 return ;
		     		 }
				 }
			}
	  		head++;
     }
     printf( "unsolvable\n" );
}

int main()
{
 	freopen( "poj 1077.in","r",stdin );
 	freopen( "poj 1077.out","w",stdout );
 	init();
 	bfs();
 	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值