码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 1043 Eight->广度优先搜索(BFS)+康托展开(全排列hash)实践

时间:2015-04-27 21:54:28      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:c   acm   算法   c++   八数码   

分析:经典的八数码问题,参考别人的代码写的,逆向广搜,把结果保存起来,之后在使用。

#include<iostream>
#include<queue>
using namespace std;

#define STATE_COUNT 363000  //因为9!=362880

int fact[]={1,1,2,6,24,120,720,5040,40320,362880};  //0到9的阶乘,用来计算hash值
char dir[4][2]={
	{0,1},{0,-1},{1,0},{-1,0}    //右,左,上,下
};
char dirchar[]="lrud";  //因为是从合法状态搜索出其他状态,方便之后返回时好处理,所以和搜索方向相反

class Eight_Puzzle
{
private:
	struct Node
	{
    	char map[3][3];
    	char x_pos_x,x_pos_y;

    	void GetMap(char* p);
	};

public:
	Eight_Puzzle(){}
	~Eight_Puzzle(){}
	void Bfs();              //广度搜索打表
	void OutPut(char* p);       //根据状态输出结果

private:
	void OutPut(int hash);
	int Get_Hash(Node p);     //获取某个状态的hash值

	char m_path[STATE_COUNT];
    bool m_vis[STATE_COUNT];
    int m_pre[STATE_COUNT];
	queue<Node> m_q;            //搜索队列
};

void Eight_Puzzle::OutPut(int hash)
{
	if(hash<=0) return ;

	printf("%c",m_path[hash]);
	OutPut(m_pre[hash]);
}

void Eight_Puzzle::OutPut(char* p)
{
	Node tmp;
	int hash;

	tmp.GetMap(p);
	hash=Get_Hash(tmp);

	if(!m_vis[hash])    //表中无该hash值,说明状态不可达
	{
		printf("unsolvable\n");
		return ;
	}
	else if(hash==0)    //标准状态,无需移动
	{
		printf("\n");
		return ;
	}
	else
	{
		OutPut(hash);
		printf("\n");
	}
}

void Eight_Puzzle::Bfs()
{
	char start[]="12345678x";
	Node tmp;
	int i,x,y;
	int hash0,hash;

	memset(m_path,0,sizeof(m_path));
	memset(m_vis,0,sizeof(m_vis));
	memset(m_pre,0,sizeof(m_pre));

	m_vis[0]=true;       //起点设置为拜访
	tmp.GetMap(start);
	m_q.push(tmp);        //起始状态入队

	while(!m_q.empty())
	{
		tmp=m_q.front();
		hash0=Get_Hash(tmp);       //队头的hash,当前步
		for(i=0;i<4;i++)
		{
			tmp=m_q.front();       //每次都重新取出队头

			x=tmp.x_pos_x+dir[i][0];
			y=tmp.x_pos_y+dir[i][1];
			if(x<0 || y<0 || x>=3 || y>=3)
				continue;

			swap(tmp.map[tmp.x_pos_x][tmp.x_pos_y],tmp.map[x][y]);
			tmp.x_pos_x=x;               //更新坐标
			tmp.x_pos_y=y;
	     	hash=Get_Hash(tmp);
			if(m_vis[hash])
				continue;

			m_vis[hash]=true;
			m_pre[hash]=hash0;
			m_path[hash]=dirchar[i];
			m_q.push(tmp);
		}
		m_q.pop();           //队头出队,状态已处理
	}
}

int Eight_Puzzle::Get_Hash(Node p)
{
	char s[10];
	int i,j,k,count;
	int hash=0;

	for(i=0;i<3;i++)
		for(j=0;j<3;j++)
		{
			count=0;
			s[i*3+j]=p.map[i][j];
			for(k=i*3+j-1;k>=0;k--)
				if(s[k]>s[i*3+j])
					count++;
			hash+=count*fact[i*3+j];
		}
	return hash;
}

void Eight_Puzzle::Node::GetMap(char* p)
{
	int i,j;
	
	i=j=0;
    while(*p)
	{
	   	if(*p>='1' && *p<='8' || *p=='x')
		{
     		map[i][j]=*p;
	   		if(map[i][j]=='x')
			{
				map[i][j]='9';
				x_pos_x=i;
				x_pos_y=j;
			}
			j++;
			if(j>=3)
			{
				i++;
				j=0;
			}
		}
		p++;
	}
}

int main()
{
	char a[50];
	Eight_Puzzle* eight_puzzle=(Eight_Puzzle*)new Eight_Puzzle;

	eight_puzzle->Bfs();          //打表,保存所有合法移动的步骤
	while(gets(a))
	{
		eight_puzzle->OutPut(a);
	}
	delete eight_puzzle;
    return 0;
}


HDU ACM 1043 Eight->广度优先搜索(BFS)+康托展开(全排列hash)实践

标签:c   acm   算法   c++   八数码   

原文地址:http://blog.csdn.net/a809146548/article/details/45315021

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!