题意:
输出八数码的路径。
题解:
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) ;
}
}