A*算法解决八数码问题

昨天啃了一阵子,终于啃下了大名鼎鼎的A*(AStar)算法。

A*跟BFS(宽度优先搜索)非常相似,只是多了一个启发函数跟结点的实时判断。

而A*算法的重点也就是启发函数,而且这没有固定的模版或者套路,完全看个人的设计能力。

其他的并不难。


参考了 http://hi.baidu.com/catro/item/4782da1769edbd721109b5e9

和       http://blueve.me/archives/684

这两篇写得非常好的文章。


废话不说了,稚嫩的代码如下:


#include 
#include 
#include 
using namespace std;

//A*八数码

// 状态结构存储
struct State
{
    int s[3][3];
    int index,pre;
    int g;
    //打印路径
    void Display()
    {
        for(int i = 0; i < 3; ++i)
        {
            for(int j = 0; j < 3; ++j)
            {
                cout << s[i][j] << ' ';
            }
            cout << endl;
        }
    }
	//优先级比较
	friend bool operator< (State n1, State n2)
    {
        return n1.g > n2.g;
    }
	bool equal(State goal)
	{
		for(int i = 0; i < 3; ++i)
        {
            for(int j = 0; j < 3; ++j)
            {
				if(s[i][j] != goal.s[i][j]) return false;
            }
        }
		return true;
	}
	int fineZero(int flag)
	{
		for(int i=0;i<3;i++)
			for(int j=0;j<3;j++)
				if(s[i][j]==0)
				{
					if(flag==0) return i;
					else return j;
				}
	}
};
 
//vector States; // 存储所有的状态
//初始状态和目标状态
State inital,goal;
//开闭表
priority_queue openTable;
vector closeTable;
int direct[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; //方向 右 左 下 上
/**
 * 启发函数
 * --------------------
 * f(s) = g(s) + h(s)
 * 其中 g(s) 由 g 数组给出
 * h(s) = 与目标状态不一致点的个数
 */
int f(State node)
{
    int rslt = node.g;  // g(s)
    for(int i = 0; i < 3; ++i)    // h(s)
		for(int j = 0; j < 3; ++j)
		{
			if(node.s[i][j] != goal.s[i][j])
			{
				rslt++;
			}
		}
    return rslt;
}

bool isMove(int goalX , int goalY)
{
	if(goalX < 0 || goalX>=3) return false;
	if(goalY < 0 || goalY>=3) return false;
	return true;
}

bool isCloseTableContain(State node)
{
	State tmp;
	for(vector::iterator ite = closeTable.begin() ; ite != closeTable.end() ;ite++)
	{
		tmp = (State)*ite;
		if(tmp.equal(node))
			return true;
	}
	return false;
}

State AStar(State start)
{
    // 初始状态
    start.g = 0;
	start.pre = -1;
    openTable.push(start);

    while(!openTable.empty())
    {
        // 找到最优的一个状态
		State preState = openTable.top(); // 获取状态索引
        openTable.pop();

        // 插入close表
		preState.index = closeTable.size();
		closeTable.push_back(preState);

		// 已找到目标状态
		if(preState.equal(goal))
		{
			return preState;
		}
        // 尝试向四个方向扩展该状态
        for(int i(0); i < 4; ++i)
        {
			State cur = preState;
			int zeroX = cur.fineZero(0);
			int zeroY = cur.fineZero(1);
			// 取得带扩展状态的空位位置
			int goalX = direct[i][0]+zeroX;
			int goalY = direct[i][1]+zeroY;
            // 确保移动合法
            if(isMove(goalX, goalY))
            {
                // 交换移动0
				int num = cur.s[goalX][goalY];
				cur.s[goalX][goalY] = 0;
				cur.s[zeroX][zeroY] = num;
 
                // 判重
                if(!isCloseTableContain(cur))
                {
                    // 将新状态置入状态序列
                    cur.g = f(cur);
					cur.pre = preState.index;
					// 插入open表
					openTable.push(cur);
                }
            }
        }
    }
}

State inputData()//录入数据
{
	State aNode;
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			cin>>aNode.s[i][j];
		}
	}
	return aNode;
}

//递归回溯求解
void disPlayWay(int index)
{
	if(index == -1) return ;
	State node = closeTable[index];
	disPlayWay(node.pre);
	node.Display();
	cout<<"->"<


你可能感兴趣的:(算法,AStar,Astar,c++,C++,算法)