| ||||||||||
Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
为什么会WA,麻烦有时间的大大们帮我看看,先谢谢了。。。我先从目的态扩展到各种状态,然后记录,每问一个,我就哈希到对应状,然后向上走到树根输出,如果哈希到对应的状态是没有出现过的,则是unsolvable。提交WA,请问这样做有什么错误?一般数据我写了测试程序测过,没问题。。 /* Wrong Answer 1217 C++ 260 5360 wolf */ #pragma warning ( disable:4786 ) #include <iostream> #include <string> #include <queue> #include <set> using namespace std; typedef struct { int pre; //到达该状态的前一状态 int move; //到达该状态的操作 int existed; //该状态是否出现过 }State; typedef struct { string s; int pos; }Node; const int MAX_N = 362884; int go[ 4 ][ 2 ] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } }; //右下左上(0123) State state[ MAX_N ]; string str; string dest( "123456780" ); char num[ 4 ]; void swap_2( char& a, char& b ) { char t = a; a = b; b = t; } void init() { int i; str.erase( str.begin(), str.end() ); str += num; for( i = 2; i <= 9; ++i ) { scanf( "%s", num ); if( num[ 0 ] == 'x' ) num[ 0 ] = '0'; str += num; } } int find_pos( const string& s ) { int i; for( i = 0; i < s.size(); ++i ) if( s[ i ] == '0' ) return i; return -1; } /* 因为BFS是从目的态出发,所以move是指从目的态到其它态的操作 因此从目的态到其它态的操作是反操作,右变成了左,上变成了下 */ char change( int i ) { switch( i ) { case 0: return 'l'; case 1: return 'u'; case 2: return 'r'; case 3: return 'd'; } return 'w'; } /* 哈希函数:本题难点。 全排列的哈希:对应位的逆序数乘以对应位的阶乘数(从0!开始)即为哈希值(0~n!-1), 可以保证哈希数在0~n!-1之间且唯一。 如:1 2 3 的全排列的哈希 1 2 3 0 * 0! + 0 * 1! + 0 * 2! = 0 1 3 2 0 * 0! + 0 * 1! + 1 * 2! = 2 2 1 3 0 * 0! + 1 * 1! + 0 * 2! = 1 2 3 1 0 * 0! + 0 * 1! + 2 * 2! = 4 3 1 2 0 * 0! + 1 * 1! + 1 * 2! = 3 3 2 1 0 * 0! + 1 * 1! + 2 * 2! = 5 */ int get_key( const string& s ) { int i, j; int cnt; int n = 1; int m = 1; int res = 0; /*求逆序数*/ for( i = 1; i < s.size(); ++i ) //第一个的逆序数必为0 { cnt = 0; for( j = 0; j < i; ++j ) { if( s[ i ] < s[ j ] ) //后边的比前边的小,逆序 ++cnt; } res += cnt * m; ++n; m = m * n; } return res; } /* 从目的往回求,一次性求出所有状态。以后只要哈希到该状态,直接输出 如果求后检测到existed仍为初值(-1),则表示该状态为不可能到达态 */ void BFS() { queue<Node> q; Node cur, next; int i; memset( state, -1, sizeof( state ) ); cur.s = dest; cur.pos = find_pos( dest ); int k = get_key( dest ); state[ k ].existed = 1; state[ k ].pre = -1; //树根结点,无父结点 q.push( cur ); while( !q.empty() ) { cur = q.front(); q.pop(); int cur_r = cur.pos / 3; int cur_c = cur.pos % 3; int cur_key = get_key( cur.s ); for( i = 0; i < 4; ++i ) { int next_r = cur_r + go[ i ][ 0 ]; int next_c = cur_c + go[ i ][ 1 ]; if( next_r >= 0 && next_r < 3 //这里可以用围墙来避免界限判断的 && next_c >= 0 && next_c < 3 ) //和写推箱子游戏一样呀!!汗。。。 { next.s = cur.s; next.pos = next_r * 3 + next_c; swap_2( next.s[ cur.pos ], next.s[ next.pos ] ); int next_key = get_key( next.s ); if( state[ next_key ].existed == -1 ) //未出现过 { state[ next_key ].move = i; state[ next_key ].pre = cur_key; state[ next_key ].existed = 1; q.push( next ); } } } } } void solve() { int key = get_key( str ); if( state[ key ].existed == -1 ) { printf( "unsolvable\n" ); return; } string res; while( state[ key ].pre != -1 ) { res += change( state[ key ].move ); key = state[ key ].pre; } puts( res.c_str() ); } int main() { #ifndef ONLINE_JUDGE FILE *fin; fin = freopen( "t.in", "r", stdin ); freopen( "t.out", "w", stdout ); if( !fin ) { printf( "reopen in file failed...\n" ); exit( 0 ); } #endif BFS(); while( scanf( "%s", num ) != EOF ) { init(); solve(); } #ifndef ONLINE_JUDGE fclose( stdin ); #endif return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator