poj-1077 八数码 【a*】

状态总数是9! = 362880 种,不算太多,可以满足广搜和A*对于空间的需求。

假如把x看做0。最大为876543210没超过Int的存储范围,所以用一个int值来表示其平面状态。 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include <vector>
#define keyMax 999983
#define target 123456780
using namespace std;
struct  node1{
	int val;//此状态的Int表示
	char step;//从上一个状态转移到这个状态做的操作
	int pre_num;//前一个状态在状态表中的编号
	int count_step;//从起点到这个状态的实际代价
};
struct node2{
	int evaluate;//评估代价
	int num;//这个状态对应的状态表中的编号
	bool operator < (const node2 &a) const {  
        return evaluate>a.evaluate; 
    }
};
int hashTable[keyMax];//哈希表记录状态是否遍历过
char direction[4]={'u','d','l','r'};
int exchange[9][4]={//exchange[i][j]表示x在位置i 做direction[j]操作 该到哪个位置
	{-1,3,-1,1},
	{-1,4,0,2},
	{-1,5,1,-1},
	{0,6,-1,4},
	{1,7,3,5},
	{2,8,4,-1},
	{3,-1,-1,7},
	{4,-1,6,8},
	{5,-1,7,-1}
};
int move[9][9]={ move[i][j] 表示 位置i移动到位置j需要几步
	{0,1,2,1,2,3,2,3,4},
	{1,0,1,2,1,2,3,2,3},
	{2,1,0,3,2,1,4,3,2},
	{1,2,3,0,1,2,1,2,3},
	{2,1,2,1,0,1,2,1,2},
	{3,2,1,2,1,0,3,2,1},
	{2,3,4,1,2,3,0,1,2},
	{3,2,3,2,1,2,1,0,1},
	{4,3,2,3,2,1,2,1,0}
};
vector<node1> state_table;//状态表
priority_queue<node2> que;//优先队列
void init()
{//初始化哈希表、将优先队列、状态表清空
	memset(hashTable,0,sizeof(hashTable));
	state_table.clear();
	while(!que.empty())
		que.pop();
}
int getValue(char *s)
{//将输入内容转换成int值表示
	int i;
	int res=0;
	int len=strlen(s);
	for(int i=0;i<len;i++)
	{
		if(s[i]<='9'&&s[i]>='1')
			res=res*10+s[i]-'0';
		else if(s[i]=='x')
			res*=10;
	}
	return res;
}
int getKey(int val)
{
	return val%keyMax;
}
void addInHashTalbe(int val)
{
	int key=getKey(val);
	while(hashTable[key])
	{
		++key;
		if(key==keyMax)
			key=0;
	}
	hashTable[key]=val;
}
bool isInHashTable(int val)
{
	int key=getKey(val);
	while(true)
	{
		if(!hashTable[key])
			return false;
		if(hashTable[key]==val)
			return true;
		++key;
		if(key==keyMax)
			key=0;
	}
}
int evaluation(int val)
{//评估函数  为每个数从状态中的位置直接到自己该到的位置的步数之和
	int res=0;
	for(int i=8;i>=0;i--)
	{
		int num=val%10-1;
		if(num==-1)
			continue;
		res+=move[i][num];
		val/=10;
	}
	return res;
}
void print_answer(int num)
{
	int pre=state_table[num].pre_num;
	if(pre==-1)
		return;
	print_answer(pre);
	printf("%c",state_table[num].step);
}
bool a_star(int val)
{
	addInHashTalbe(val);
	state_table.push_back((node1){val,'s',-1,0});
	que.push((node2){evaluation(val),state_table.size()-1});
	while(!que.empty())
	{
		node2 this_state=que.top();que.pop();
		if(state_table[this_state.num].val==target)
		{
			print_answer(this_state.num);
			return true;
		}
		int i;
		int t=state_table[this_state.num].val,loc;
		int v[9];
		for(i=8;i>=0;i--)
		{
			if(t%10==0)
				loc=i;
			v[i]=t%10;
			t/=10;
		}
		for(i=0;i<4;i++)
		{
			if(exchange[loc][i]==-1)//不能转移的方向标记为-1
				continue;
			t=0;
			for(int j=0;j<=8;j++)
			{
				if(j==loc)
					t=t*10+v[exchange[loc][i]];
				else if(j==exchange[loc][i])
					t=t*10+v[loc];
				else t=t*10+v[j];
			}
			if(!isInHashTable(t))
			{
				addInHashTalbe(t);
				state_table.push_back((node1){t,direction[i],this_state.num,state_table[this_state.num].count_step+1});
				que.push((node2){state_table[this_state.num].count_step+1+evaluation(t),state_table.size()-1});
			}
		}
	}
	return false;
}
int main()
{
	char ch[50];
	while(gets(ch)!=NULL)
	{
		init();
		int val=getValue(ch);
		if(!a_star(val))
			printf("unsolvable");
		printf("\n");
	}
	return 0;
}


你可能感兴趣的:(a)