这一次让偶仍然用拿手的穷举法来写一个自动解推箱子问题的机器人吧。
偶使用了yzwykkldczsh同志写的状态机模板以及该模板的配套算法“万用智能超级无穷迭代动态规划递归算法”(为纪念友人Jornathan Ding,此算法又称为H>D算法)。它的基本原理是:
1.将每一步的人和箱子的数据放到一个记录里,此记录表示当前状态
2.设置当前状态为已访问
3.遍历下面的每一个子状态。若所有子状态都已访问或无解,则当前步也无解
4.若子状态有解,则恢复此状态为未访问。
对所有子状态,重复1-4步。
此算法可解很多智力题,比如倒酒问题、过河问题,等等。
偶的测试程序里写死了地图。实际应用中应当从文件中载入。下面帖出测试程序代码:
ACIter.h源码
/*
* CACIter:用于记录结点访问状态的辅助模板类。TNodeKey为唯一确定当前状态的哈希值类型,应当是一个struct。
* 三种状态是:nsNone:无或不在结点访问状态表中;nsVisiting:正在访问;nsDead:已死亡
*/
#pragma once
#include <map>
enum NodeStatus {
nsNone,
nsVisiting,
nsDead
};
template<typename _Ty>
class CMemLessTempl
: public std::binary_function<_Ty, _Ty, bool>
{
public:
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{
/* 对于两个struct的比较,用内存逐byte比较即可。
要注意的是struct如果不是按字节对齐的话,需要在初始化时memset为全0,否则可能有干扰数据 */
unsigned char *p1 = (unsigned char *)&_Left, *p2 = (unsigned char *)&_Right;
return memcmp(p1, p2, sizeof(_Ty)) < 0;
}
};
template<typename TNodeKey>
class CACIter
{
private:
typedef std::map<TNodeKey, enum NodeStatus, CMemLessTempl<TNodeKey> > NODESTATUSMAP;
/* 结点访问状态记录树 */
NODESTATUSMAP m_NodeStatus;
public:
/* 获取当前结点访问状态。找不到也返回nsNone */
virtual enum NodeStatus GetStatus(TNodeKey key)
{
NODESTATUSMAP::iterator it = m_NodeStatus.find(key);
if ( it == m_NodeStatus.end() ) return nsNone;
return it->second;
}
/* 设置当前结点访问状态。如果设为nsNone,则可删除这个结点 */
virtual void SetStatus(TNodeKey key, enum NodeStatus status)
{
if (status == nsNone)
{
NODESTATUSMAP::iterator it = m_NodeS