虽然是过了
但因为一开始hash值存在结构体里所以TLE
下次还是打表吧
#include <algorithm>
#include <iostream>
#include <math.h>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string.h>
using namespace std;
struct Node {
char map[ 3 ][ 3 ];
int x, y;
int g, h; // g是已经走过的步数,h是剩下距离终点的距离
bool operator< ( const Node t ) const { return h + g > t.h + t.g; }
} cur, nex;
char str[ 100 ];
int check_rev () //逆序数对,判断不可能的状况
{
int i, j, k;
int s[ 20 ];
int cnt = 0;
for ( i = 0; i < 3; i++ ) {
for ( j = 0; j < 3; j++ ) {
s[ 3 * i + j ] = cur.map[ i ][ j ];
if ( s[ 3 * i + j ] == 'x' )
continue;
for ( k = 3 * i + j - 1; k >= 0; k-- ) {
if ( s[ k ] == 'x' )
continue;
if ( s[ k ] > s[ 3 * i + j ] )
cnt++;
}
}
}
if ( cnt % 2 )
return 0;
return 1;
}
//康托展开 0~8的阶乘
int factorial[ 9 ] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int get_hash ( Node a ) //康托
{
int i, j, k;
int s[ 20 ];
int ans = 0;
for ( i = 0; i < 3; i++ ) {
for ( j = 0; j < 3; j++ ) {
s[ 3 * i + j ] = a.map[ i ][ j ];
int cnt = 0;
for ( k = 3 * i + j - 1; k >= 0; k-- ) {
if ( s[ k ] > s[ 3 * i + j ] )
cnt++;
}
ans = ans + factorial[ i * 3 + j ] * cnt;
}
}
return ans;
}
// 3*3每个点的indx
int pos[][ 2 ] = {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}, {2, 0}, {2, 1}, {2, 2}};
int get_h ( Node a ) //得到距离终点距离的值
{
int i, j;
int ans = 0;
for ( i = 0; i < 3; i++ ) {
for ( j = 0; j < 3; j++ ) {
if ( a.map[ i ][ j ] == 'x' )
continue;
int k = a.map[ i ][ j ] - '1';
ans += abs ( pos[ k ][ 0 ] - i ) + abs ( pos[ k ][ 1 ] - j );
}
}
return ans;
}
//判断是否出界
inline bool path ( int x, int y ) {
if ( x >= 0 && x < 3 && y >= 0 && y < 3 )
return true;
return false;
}
bool vis[ 500000 ];
int dir[ 4 ][ 2 ] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
//回溯用
char ch[ 500000 ];
int pre[ 500000 ];
char way[ 10 ] = "drul";
void A_star () {
memset ( vis, 0, sizeof ( vis ) );
cur.g = 0;
cur.h = get_h ( cur );
priority_queue<Node> Q;
Q.push ( cur );
while ( !Q.empty () ) {
Node a = Q.top ();
Q.pop ();
int k_s = get_hash ( a );
for ( int i = 0; i < 4; i++ ) {
nex = a;
nex.x += dir[ i ][ 0 ];
nex.y += dir[ i ][ 1 ];
if ( path ( nex.x, nex.y ) ) {
// swap
nex.map[ a.x ][ a.y ] = a.map[ nex.x ][ nex.y ];
nex.map[ nex.x ][ nex.y ] = 'x';
nex.g += 1;
nex.h = get_h ( nex );
//找个变量存一下( 存在结构体里会TLE )
int k_n = get_hash ( nex );
if ( !vis[ k_n ] ) {
vis[ k_n ] = true;
Q.push ( nex );
pre[ k_n ] = k_s;
ch[ k_n ] = way[ i ];
if ( k_n == 0 )
return;
}
}
}
}
}
int main () {
int i, len, x, y;
//输入
while ( cin.getline ( str, 100 ) ) {
x = y = 0;
len = strlen ( str );
for ( i = 0; i < len; i++ ) {
if ( ( str[ i ] >= '0' && str[ i ] <= '9' ) || str[ i ] == 'x' ) {
cur.map[ x ][ y ] = str[ i ];
if ( cur.map[ x ][ y ] == 'x' ) {
cur.x = x;
cur.y = y;
}
y++;
if ( y == 3 ) {
y = 0;
x++;
}
}
}
//判断逆序对数,能否转换成最后结果
if ( !check_rev () ) {
printf ( "unsolvable\n" );
continue;
}
int sa = get_hash ( cur );
A_star ();
//输出
stack<char> s;
int now = 0;
while ( sa != now ) {
s.push ( ch[ now ] );
now = pre[ now ];
}
while ( !s.empty () ) {
putchar ( s.top () );
s.pop ();
}
printf ( "\n" );
}
return 0;
}