poj 1077 解题报告
2013-02-27 21:28
316 查看
最近学人工智能,要学A*算法,就重新做这道题经典的8数码问题,传说不做这道题人生不完整呢我之前是用的广搜暴力搞的,不过太慢了,还要说说我的hash方法,我是用康托展开来hash的,这个东西是算一个排列在所有排列大小排多少,比如(1,2,3)有6个排列,321是最大的就是第六个。还有就是康托展开的逆运算,就是知道是第几大的,算出这个排列来;
康托展开:
它的逆运算:
就是这样的,,,
用爆搜的代码是这样的:
然后我用了A*算法,,启发函数是网上找的:
然后我自己想了一个启发函数
结果是这样了:
注释的部分就是被改掉的
康托展开:
long cantor( int s[] ) { int i , j , t ; long num = 0 ; for( i = 0 ; i < 9 - 1 ; i ++ ) { t = 0 ; for( j = i + 1 ; j < 9 ; j ++ ) if( s[j] < s[i] ) ++ t ; num += fac[9-i-1] * t ; } return num ; }
它的逆运算:
void uncantor( int s[] , int ct ) { int i , j , t , r ; bool p[10] = { 0 } ; for( i = 0 ; i < 9 ; i ++ ) { t = ct / fac[9 - i - 1] + 1 ; ct %= fac[9 - i - 1] ; r = 0 , j = 1 ; while( 1 ) { if( !p[j] ) r ++ ; if( r == t ) break ; j ++ ; } s[i] = j ; p[j] = 1 ; } }
就是这样的,,,
用爆搜的代码是这样的:
Problem: 1077 | User: 925695531 | |
Memory: 2404K | Time: 547MS | |
Language: C++ | Result: Accepted |
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
using namespace std;
int fac[10] ;
int pre[400000] ;
char dir[400000] ;
void init( )
{
fac[0] = 1 ;
for( int i = 1 ; i <= 9 ; i ++ )
fac[i] = i * fac[i-1] ;
}
long cantor( int s[] ) { int i , j , t ; long num = 0 ; for( i = 0 ; i < 9 - 1 ; i ++ ) { t = 0 ; for( j = i + 1 ; j < 9 ; j ++ ) if( s[j] < s[i] ) ++ t ; num += fac[9-i-1] * t ; } return num ; }
void uncantor( int s[] , int ct ) { int i , j , t , r ; bool p[10] = { 0 } ; for( i = 0 ; i < 9 ; i ++ ) { t = ct / fac[9 - i - 1] + 1 ; ct %= fac[9 - i - 1] ; r = 0 , j = 1 ; while( 1 ) { if( !p[j] ) r ++ ; if( r == t ) break ; j ++ ; } s[i] = j ; p[j] = 1 ; } }
int main()
{
int tc[9] , ot , t , i;
char c[2] ;
bool ok = 0 ;
queue<int> q ;
init() ;
memset( pre , 0 , sizeof( pre ) ) ;
for( i = 0 ; i < 9 ; i ++ )
{
scanf( "%s" , c ) ;
if( c[0] == 'x' ) tc[i] = 9 ;
else tc[i] = c[0] - '0' ;
}
t = cantor( tc ) ;
pre[t] = -1 ;
q.push( t ) ;
while( !q.empty() )
{
ot = q.front() ;
q.pop() ;
if( ot == 0 ) { ok = 1 ; break ; }
uncantor( tc , ot ) ;
for( i = 0 ; i < 9 ; i ++ ) if( tc[i] == 9 ) break ;
if( i != 0 && i != 1 && i != 2 )
{
swap( tc[i] , tc[i-3] ) ;
t = cantor(tc) ;
if( !pre[t] )
{
pre[t] = ot ;
dir[t] = 'u' ;
q.push(t) ;
}
swap( tc[i] , tc[i-3] ) ;
}
if( i != 6 && i != 7 && i != 8 ) //down
{
swap( tc[i] , tc[i+3] ) ;
t = cantor( tc ) ;
if( !pre[t] )
{
pre[t] = ot ;
dir[t] = 'd' ;
q.push(t) ;
}
swap( tc[i] , tc[i+3] ) ;
}
if( i != 0 && i != 3 && i != 6 ) // left
{
swap( tc[i] , tc[i-1] ) ;
t = cantor( tc ) ;
if( !pre[t] )
{
pre[t] = ot ;
dir[t] = 'l' ;
q.push( t ) ;
}
swap( tc[i] , tc[i-1] ) ;
}
if( i != 2 && i != 5 && i != 8 ) // right
{
swap( tc[i] , tc[i+1] ) ;
t = cantor( tc ) ;
if( !pre[t] )
{
pre[t] = ot ;
dir[t] = 'r' ;
q.push(t) ;
}
swap( tc[i] , tc[i+1] ) ;
}
}
if( ok )
{
stack<char> s ;
while( pre[ot] != -1 )
{
s.push( dir[ot] ) ;
ot = pre[ot] ;
}
while( !s.empty() )
{
printf( "%c" , s.top() ) ;
s.pop() ;
}
}
else printf( "unsolvable\n" ) ;
}
然后我用了A*算法,,启发函数是网上找的:
Problem: 1077 | User: 925695531 | |
Memory: 6988K | Time: 16MS | |
Language: G++ | Result: Accepted |
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
using namespace std ;
int fac[10] ;
struct Node
{
int pre ;
int step ;
int h ;
char dir ;
bool vis ;
} node[400000] ;
char dir[400000] ;
bool vis[400000] ;
void init()
{
fac[0] = 1 ;
for( int i = 1 ; i <= 9 ; i ++ )
fac[i] = i * fac[i-1] ;
}
long cantor( int s[] ) { int i , j , t ; long num = 0 ; for( i = 0 ; i < 9 - 1 ; i ++ ) { t = 0 ; for( j = i + 1 ; j < 9 ; j ++ ) if( s[j] < s[i] ) ++ t ; num += fac[9-i-1] * t ; } return num ; }
void uncantor( int s[] , int ct ) { int i , j , t , r ; bool p[10] = { 0 } ; for( i = 0 ; i < 9 ; i ++ ) { t = ct / fac[9 - i - 1] + 1 ; ct %= fac[9 - i - 1] ; r = 0 , j = 1 ; while( 1 ) { if( !p[j] ) r ++ ; if( r == t ) break ; j ++ ; } s[i] = j ; p[j] = 1 ; } }
class cmp
{
public:
bool operator()(int sa,int sb)
{
return node[sa].h+node[sa].step>node[sb].h+node[sb].step;
}
};
int h( int s[] )
{
int H = 0 ;
for( int i = 0 ; i < 9 ; i ++ )
{
if( s[i] != 9 ) H += abs ( double ( ( s[i] - 1 ) / 3 - i / 3 ) ) + abs ( double ( ( s[i] - 1 ) % 3 - i % 3 ) ) ;
//if( s[i] != 9 && i == s[i] - 1 ) H ++ ;
}
return H ;
}
bool AStar( int s[] )
{
int tc[9] , t , i , flag = 0 ;
//if( !isResolve( s ) ) return false ;
memset( vis , 0 , sizeof( vis ) ) ;
priority_queue< int , vector<int> , cmp > q ;
int temp = cantor( s ) ;
node[temp].pre = -1 ;
node[temp].step = 0 ;
node[temp].h = h( s ) ;
q.push( temp ) ;
while( !q.empty() )
{
temp = q.top() ;
q.pop() ;
if( temp == 0 ){
flag = 1 ;
break ;
}
if( vis[temp] ) continue ;
uncantor( tc , temp ) ;
for( i = 0 ; i < 9 ; i ++ ) if( tc[i] == 9 ) break ;
if( i != 0 && i != 1 && i != 2 )
{
swap( tc[i] , tc[i-3] ) ;
t = cantor(tc) ;
if( !node[t].pre )
{
node[t].pre = temp ;
node[t].step = node[temp].step + 1 ;
node[t].h = h( tc ) ;
dir[t] = 'u' ;
q.push(t) ;
}
swap( tc[i] , tc[i-3] ) ;
}
if( i != 6 && i != 7 && i != 8 )
{
swap( tc[i] , tc[i+3] ) ;
t = cantor( tc ) ;
if( !node[t].pre )
{
node[t].pre = temp ;
node[t].step = node[temp].step + 1 ;
node[t].h = h( tc ) ;
dir[t] = 'd' ;
q.push(t) ;
}
swap( tc[i] , tc[i+3] ) ;
}
if( i != 0 && i != 3 && i != 6 )
{
swap( tc[i] , tc[i-1] ) ;
t = cantor( tc ) ;
if( !node[t].pre )
{
node[t].pre = temp ;
node[t].step = node[temp].step + 1 ;
node[t].h = h( tc ) ;
dir[t] = 'l' ;
q.push(t) ;
}
swap( tc[i] , tc[i-1] ) ;
}
if( i != 2 && i != 5 && i != 8 )
{
swap( tc[i] , tc[i+1] ) ;
t = cantor( tc ) ;
if( !node[t].pre )
{
node[t].pre = temp ;
node[t].step = node[temp].step + 1 ;
node[t].h = h( tc ) ;
dir[t] = 'r' ;
q.push( t ) ;
}
swap( tc[i] , tc[i+1] ) ;
}
}
return flag ;
}
int main()
{
int tc[9] , ot = 0 , i ;
char ch ;
init() ;
for( i = 0 ; i < 9 ; i ++ )
{
cin >> ch ;
if( ch == 'x' ) tc[i] = 9 ;
else tc[i] = ch - '0' ;
}
if( AStar( tc ) )
{
stack < char > s ;
while( node[ot].pre != -1 )
{
s.push( dir[ot] ) ;
ot = node[ot].pre ;
}
while( !s.empty() )
{
cout << s.top() ;
s.pop() ;
}
cout << endl ;
}
else cout << "unsolvable" << endl ;
return 0 ;
}
然后我自己想了一个启发函数
结果是这样了:
Problem: 1077 | User: 925695531 | |
Memory: 6988K | Time: 0MS | |
Language: G++ | Result: Accepted |
#include <iostream> #include <cstring> #include <queue> #include <stack> #include <cmath> using namespace std ; struct Node{ int pre , h , step ; char dir ; bool vis ; } node[400000] ; struct cmp { bool operator () ( int a , int b ) { //return node[a].h + node[a].step > node[b].h + node[b].step ; return node[a].h < node[b].h ; } } ; int fac[10] ; void init() ; int cantor( int s[] ) ; void uncantor( int s[] , int num ) ; int h( int s[] ) ; bool AStar( int s[] ) ; int main() { int str[10] , State = 0 ; char ch ; init() ; for( int i = 0 ; i < 9 ; i ++ ) { cin >> ch ; if( ch == 'x' ) str[i] = 9 ; else str[i] = ch - '0' ; } if( AStar( str ) ) { stack < char > s ; while( node[State].pre != -1 ) { s.push( node[State].dir ) ; State = node[State].pre ; } while( !s.empty() ) { cout << s.top() ; s.pop() ; } cout << endl ; } else cout << "unsolvable" << endl ; return 0 ; } void init() { fac[0] = 1 ; for( int i = 1 ; i <= 9 ; i ++ ) fac[i] = i * fac[i-1] ; } int cantor( int s[] ) //康托展开 { int num = 0 , t ; for( int i = 0 ; i < 9 ; i ++ ) { t = 0 ; for( int j = i + 1 ; j < 9 ; j ++ ) if( s[i] > s[j] ) t ++ ; num += fac[9 - i - 1] * t ; } return num ; } void uncantor( int s[] , int num ) //逆向康托展开 { int j , t , r ; bool p[10] ; memset( p , 0 , sizeof( p ) ) ; for( int i = 0 ; i < 9 ; i ++ ) { t = num / fac[9 - i - 1] + 1 ; num %= fac[9 - i - 1] ; r = 0 , j = 1 ; while( 1 ) { if( !p[j] ) r ++ ; if( r == t ) break ; j ++ ; } s[i] = j ; p[j] = 1 ; } } int h( int s[] ) //估价函数 { int H = 0 ; for( int i = 0 ; i < 9 ; i ++ ) //if( s[i] != 9 ) H += abs ( double ( ( s[i] - 1 ) / 3 - i / 3 ) ) + // abs ( double ( ( s[i] - 1 ) % 3 - i % 3 ) ) ; if( s[i] != 9 && i == s[i] - 1 ) H ++ ; return H ; } bool AStar( int s[] ) //A* { int str[9] , flag = 0 , i , t ; memset( node , 0 , sizeof( node ) ) ; priority_queue< int , vector<int> , cmp > q ; int temp = cantor( s ) ; node[temp].step = 0 ; node[temp].pre = -1 ; node[temp].h = h( s ) ; q.push( temp ) ; while( !q.empty() ) { temp = q.top() ; q.pop() ; if( temp == 0 ) { flag = 1 ; break ; } if( node[temp].vis ) continue ; uncantor( str , temp ) ; for( i = 0 ; i < 9 ; i ++ ) if( str[i] == 9 ) break ; if( i != 0 && i != 1 && i != 2 ) { swap( str[i] , str[i-3] ) ; t = cantor( str ) ; if( !node[t].pre ) { node[t].pre = temp ; node[t].step = node[temp].step + 1 ; node[t].h = h( str ) ; node[t].dir = 'u' ; q.push( t ) ; } swap( str[i] , str[i-3] ) ; } if( i != 6 && i != 7 && i != 8 ) { swap( str[i] , str[i+3] ) ; t = cantor( str ) ; if( !node[t].pre ) { node[t].pre = temp ; node[t].step = node[temp].step + 1 ; node[t].h = h( str ) ; node[t].dir = 'd' ; q.push( t ) ; } swap( str[i] , str[i+3] ) ; } if( i != 0 && i != 3 && i != 6 ) { swap( str[i] , str[i-1] ) ; t = cantor( str ) ; if( !node[t].pre ) { node[t].pre = temp ; node[t].step = node[temp].step + 1 ; node[t].h = h( str ) ; node[t].dir = 'l' ; q.push( t ) ; } swap( str[i] , str[i-1] ) ; } if( i != 2 && i != 5 && i != 8 ) { swap( str[i] , str[i+1] ) ; t = cantor( str ) ; if( !node[t].pre ) { node[t].pre = temp ; node[t].step = node[temp].step + 1 ; node[t].h = h( str ) ; node[t].dir = 'r' ; q.push( t ) ; } swap( str[i] , str[i+1] ) ; } } return flag ; }
相关文章推荐
- POJ 1077 解题报告
- POJ 1077 解题报告
- 【解题报告】POJ-1467 Symbolic Derivation
- poj 1811解题报告
- poj解题报告——3414
- poj解题报告——3267
- POJ 1032 解题报告
- poj 1265-Area解题报告
- 线段树的典型应用之POJ 2823 Sliding Window解题报告
- POJ 2407 Relatives 解题报告(欧拉函数水题)
- POJ1523解题报告 求点割集
- POJ 1002 487-3279 [解题报告] Java
- POJ1005解题报告
- POJ 3735 Training little cats 解题报告(矩阵构造+快速幂优化)
- POJ 1423 解题报告
- POJ 2976 Dropping tests 解题报告(二分)
- POJ 1001 解题报告 高精度大整数乘法模版
- POJ 1753 Flip Game (递归枚举)解题报告
- 归并排序与逆序对问题---(解题报告)POJ1804---Brainman
- poj分类解题报告索引