hdu 1043 八数码路径 双向bfs + 康拓展开hash + 判无解剪枝

题意:

输出八数码的路径。

题解:

1.以给出的数字为起点,以最终的目标数字为另一起点,进行双向bfs

2.康拓展开hash可以标记和存储路径,但是因为9e8过大,map只能标记而不能存储路径。

康拓展开讲解:https://blog.csdn.net/qq_38701476/article/details/81003290

3.本来前两步写完后认为大功告成,结果差了判无解的剪枝一直T。除x外的数字变为一维数组后,若逆序奇偶性与12345678不同,则无解。思考一下就知道了。

#include<iostream>
#include<stdio.h>
#include<queue>
#include<map>
#include<string.h>
#include<math.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std ;
struct node
{
	int a[10] ;
	int cur ;
	int cantor_num ;
} ;
queue <node> q[2] ;
int dire[4] = {-3 , 3 , -1 , 1} ;
char s1[4] = {'u' , 'd' , 'l' , 'r'} ;
char s2[4] = {'d' , 'u' , 'r' , 'l'} ;
int num , cnt = 0 ;
char ans1[1000005] ;
int pre_num[1000005] ;
int pre_char[1000005] ;
int next_num[1000005] ;
int next_char[1000005] ;
bool vis[2][1000005] ;
int change_cantor(node a , int k)
{
	int i , j ;
    int ans = 0; 
    if(k == 0 && a.cur < 3) return -1 ;
    if(k == 1 && a.cur > 5) return -1 ;
    if(k == 2 && a.cur % 3 == 0) return -1 ;
    if(k == 3 && a.cur % 3 == 2) return -1 ;
    swap(a.a[a.cur] , a.a[a.cur + dire[k]]) ;
	for(i = 0 ; i < 9 ; i ++) 
	{ 
	  int x = 0 ; 
	  int c = 1 , m = 1 ;//c记录后面的阶乘 
	  for(j = i + 1 ; j < 9 ; j ++) 
	  { 
	      if(a.a[j] < a.a[i])
		     x ++ ; 
			 m *= c ; 
			 c ++ ; 
	  } 
	  ans += x * m ; 
	} 
	return ans ;
}
int cantor(int num)
{
	int i , j ;
	int a[10] ;
	for(i = 8 ; i >= 0 ; i --)
    {
    	a[i] = num % 10 ;
		num /= 10 ; 
    }
    int ans=0; 
	for(i = 0 ; i < 9 ; i ++) 
	{ 
	  int x = 0 ; 
	  int c = 1 , m = 1 ;//c记录后面的阶乘 
	  for(j = i + 1 ; j < 9 ; j ++) 
	  { 
	      if(a[j] < a[i])
		     x ++ ; 
			 m *= c ; 
			 c ++ ; 
	  } 
	  ans += x * m ; 
	} 
	return ans ;
}
void output_pre(int num1)
{
	if(num1 == cantor(num))
	   return ;
	output_pre(pre_num[num1]) ;
	printf("%c" , s1[pre_char[num1]]) ;
}
void output_next(int num1)
{
	if(num1 == cantor(123456789))
	   return ;
	printf("%c" , s2[next_char[num1]]) ;
	output_next(next_num[num1]) ;
}
void output(int num1)
{
	output_pre(num1) ;
	output_next(num1) ;
	printf("\n") ;
}
void bfs(node a)
{
	int i , temp ;
	int num1 , num2 ;
	node b , c ;
	int hash ;
	memset(vis , 0 , sizeof(vis)) ;
	while(!q[0].empty())
		q[0].pop() ;
	q[0].push(a) ; 
	while(!q[1].empty())
		q[1].pop() ;
	for(i = 0 ; i < 9 ; i ++)
	    b.a[i] = i + 1 ;
	b.cantor_num = cantor(123456789) ;
	b.cur = 8 ;	
	q[1].push(b) ; 
    vis[0][cantor(num)] = 1 ;
    vis[1][cantor(123456789)] = 1 ;
    while(!q[0].empty() && !q[1].empty())
    {
    	b = q[0].front() ;
        q[0].pop() ;
        for(i = 0 ; i < 4 ; i ++)
        {
    	    hash = change_cantor(b , i) ;
    	    if(hash == -1)
    	       continue ;
			if(!vis[0][hash]) 
	        {
	        	vis[0][hash] = 1 ;
	        	pre_num[hash] = b.cantor_num ;
	        	pre_char[hash] = i ;
			    if(vis[1][hash])
			    {
			    	//printf("0\n") ;
			    	output(hash) ;
			    	return ;
				}
				memcpy(c.a , b.a , sizeof(b.a)) ;
				swap(c.a[b.cur] , c.a[b.cur + dire[i]]) ; 
				c.cur = b.cur + dire[i] ;
				c.cantor_num = hash ;
				q[0].push(c) ;
			}
		}
		b = q[1].front() ;
        q[1].pop() ;
        for(i = 0 ; i < 4 ; i ++)
        {
    	    hash = change_cantor(b , i) ;
    	    if(hash == -1)
    	       continue ;
			if(!vis[1][hash]) 
	        {
	        	vis[1][hash] = 1 ;
	        	next_num[hash] = b.cantor_num ;
	        	next_char[hash] = i ;
				if(vis[0][hash])
			    {
			    	//printf("1\n") ;
			    	output(hash) ;
			    	return ;
				}
				memcpy(c.a , b.a , sizeof(b.a)) ;
				swap(c.a[b.cur] , c.a[b.cur + dire[i]]) ; 
				c.cur = b.cur + dire[i] ;
				c.cantor_num = hash ;
				q[1].push(c) ;
			}
		}
	}
}
int main()
{
	char s[2] ;
    int i , j , ni_num ;
    node a ;
	while(scanf("%s" , s) != EOF)
	{
		num = 0 ;
	  	if(s[0] == 'x')
	  	{
	  	   num = num * 10 + 9 ;
		   a.cur = 0 ;	
		}
	  	else
	  	   num = num * 10 + s[0] - '0' ;
	  	a.a[0] = num ; 
	  	for(i = 0 ; i < 8 ; i ++)
	  	{
	  	   scanf("%s" , s) ;
	  	   if(s[0] == 'x')
	  	   {
	  	   	  num = num * 10 + 9 ;
	  	   	  a.cur = i + 1 ;
		   }
	  	   else
	  	      num = num * 10 + s[0] - '0' ;	
	  	   a.a[i + 1] = num % 10 ; 
		}
		if(num == 123456789)
		{
		   printf("\n") ;
		   continue ;	
		}
		ni_num = 0 ;
		for(i = 0 ; i < 8 ; i ++)
		   for(j = i + 1 ; j < 9 ; j ++)
		      if(a.a[i] != 9 && a.a[j] != 9 && a.a[i] > a.a[j])
		         ni_num ++ ;
	    if(ni_num % 2 == 1)
	    {
	       printf("unsolvable\n") ;
		   continue ;	
		}
		a.cantor_num = cantor(num) ;
		bfs(a) ;
	}	
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/87915987