poj 1077 八數碼

用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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章