用a*算法沒有想到怎麼優化每個節點狀態需要複製上次狀態的代價,導致tle。
使用ida* ,但是bound上界是靠直觀感覺,並沒有想到合適的估算方法
ida*
// poj 1077 八數碼 IDA*
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
char toCompare[3][4]={"123","456","789"};
char chessBoard[3][4];
bool ok=false;
int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
const int MAXN=9*8*7*6*5*4*3*2+2;
bool h[MAXN];
int fac[10],x,y;
string dest="udlr";
// 預處理階乘
void getFac(){
fac[0]=1;
for(int i=1;i<10;++i)
fac[i]=fac[i-1]*i;
}
// 利用康託展開hash全排列,返回康託展開的值
int getCanton(){
int a[9];
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
a[i*3+j]=chessBoard[i][j]-'0';
int canton=0;
for(int i=0;i<9;++i){
int cnt=0;
for(int j=i+1;j<9;++j){
if(a[i]>a[j])
++cnt;//逆序值
}
canton+=cnt*fac[8-i];
}
return canton;
}
int countDif(){
int cnt=0;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
if(toCompare[i][j]!=chessBoard[i][j])
++cnt;
}
}
return cnt;
}
// 迭代加深搜索
void dfs(int deep,int limit,string path){
if(deep>limit || ok || countDif()+deep>limit)
return;
int canton=getCanton();
if(!canton){//目標狀態canton值爲0
ok=true;
cout<<path<<endl;
return;
}
for(int i=0;i<4;++i){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=0 && xx<3 && yy>=0 && yy<3){
swap(chessBoard[xx][yy],chessBoard[x][y]);
int canton=getCanton();
if(!h[canton]){
h[canton]=true;
x+=dx[i];
y+=dy[i];
dfs(deep+1,limit,path+dest[i]);
x-=dx[i];
y-=dy[i];
}
swap(chessBoard[xx][yy],chessBoard[x][y]);
}
}
}
int main(){
getFac();
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
cin>>chessBoard[i][j];
if(chessBoard[i][j]=='x'){
chessBoard[i][j]='9';
x=i;
y=j;
}
}
}
int limit=1;//迭代加深
for(;limit<100;++limit){
ok=false;
memset(h,false,sizeof(h));
string path;
dfs(0,limit,path);
if(ok)
break;
}
if(!ok)
cout<<"unsolvable"<<endl;
return 0;
}
A* TLE
//poj1077 八數碼 A*
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int fac[13];//預處理階乘
bool h[1000000];//hash
char toCompare[3][4]={"123","456","78x"};//目標矩陣
struct Node{
char b[3][3];//棋盤board狀態
int deep,dif;//深度g和不在位數h,f=g+h爲啓發函數
int x,y,canton;//x的期盼位置,和當前狀態康託展開hash值
string ans;//path
Node(){
deep=dif=x=y=canton=0;
ans.clear();
memset(b,0,sizeof(b));
}
Node(const Node &r){
*this=r;
}
Node& operator=(const Node &r){
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
b[i][j]=r.b[i][j];
deep=r.deep;
dif=r.dif;
ans=r.ans;
x=r.x;
y=r.y;
canton=r.canton;
return *this;
}
//四種移動
bool left(){
if(y==0) return false;
swap(b[x][y],b[x][y-1]);
--y;
ans+='l';
countDif();
getCanton();
++deep;
return true;
}
bool right(){
if(y==2) return false;
swap(b[x][y],b[x][y+1]);
++y;
ans+='r';
countDif();
getCanton();
++deep;
return true;
}
bool up(){
if(x==0) return false;
swap(b[x][y],b[x-1][y]);
--x;
ans+='u';
countDif();
getCanton();
++deep;
return true;
}
bool down(){
if(x==2) return false;
swap(b[x][y],b[x+1][y]);
++x;
ans+='d';
countDif();
getCanton();
++deep;
return true;
}
// 計算不在位獎牌數
void countDif(){
dif=0;
for(int i=0;i<3;++i)
for(int j=0;j<3;++j)
if(b[i][j]!=toCompare[i][j])
++dif;
}
// 利用康託展開作爲hash函數判重
void getCanton(){
int num[9];
canton=0;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
if(b[i][j]=='x'){
num[i*3+j]=9;
}
else{
num[i*3+j]=b[i][j]-'0';
}
}
}
for(int i=0;i<9;++i){
int sum=0;
for(int j=i-1;j>=0;--j){
if(num[j]<num[i])
++sum;
}
canton+=(num[i]-1-sum)*fac[8-i];
}
}
//重載篇序符,維護f排序的priority_queen
friend bool operator<(const Node& l,const Node& r){
return l.deep+l.dif>r.deep+r.dif;
}
}now;
string bfs(){
priority_queue<Node> q;
q.push(now);
while(!q.empty()){
now=q.top();
if(now.dif==0)
return now.ans;
q.pop();
Node next[4]={now,now,now,now};
if(next[0].down() && !h[next[0].canton]){
h[next[0].canton]=true;
q.push(next[0]);
}
if(next[1].left() && !h[next[1].canton] ){
h[next[1].canton]=true;
q.push(next[1]);
}
if(next[2].right() && !h[next[2].canton]){
h[next[2].canton]=true;
q.push(next[2]);
}
if(next[3].up() && !h[next[3].canton]){
h[next[3].canton]=true;
q.push(next[3]);
}
}
return "unsolvable";
}
int main(){
// 預處理階乘
fac[0]=1;
for(int i=1;i<=9;++i)
fac[i]=fac[i-1]*i;
memset(h,false,sizeof(h));
int t;
for(int i=0;i<3;++i){
for(int j=0;j<3;++j){
cin>>now.b[i][j];
if(now.b[i][j]=='x'){
now.x=i;
now.y=j;
}
}
}
now.countDif();
now.getCanton();
h[now.canton]=true;
string output=bfs();
// if(output.empty())
// output="unsolvable";
cout<<output<<endl;
return 0;
}