其他语言

本类阅读TOP10

·基于Solaris 开发环境的整体构思
·使用AutoMake轻松生成Makefile
·BCB数据库图像保存技术
·GNU中的Makefile
·射频芯片nRF401天线设计的分析
·iframe 的自适应高度
·BCB之Socket通信
·软件企业如何实施CMM
·入门系列--OpenGL最简单的入门
·WIN95中日志钩子(JournalRecord Hook)的使用

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
过河问题的算法--有限状态机

作者:未知 来源:月光软件站 加入时间:2005-5-13 月光软件站

过河问题大家都知道,不多说了.
解决这个问题的经典方法就是使用有限状态机. 根据人,狼,羊,菜,在不同河岸,可以抽象出N种不同的状态.某些状态之间可以转换. 这些转换就是运算了. 我们的目的就是找到一组这样的运算,可以从初始状态转换到终止状态. 其间的状态必需都是合法的. C++代码如下:

/*-------------------------------------
  农夫,狼,羊, 菜,过河
  --------------------------------------*/
#include <list>
#include <iostream>


enum PLACE
{
 NO,    // 没有过河的
 YES,   // 已经过河了
};

// 状态
typedef struct
{
 PLACE man;    // 人的状态
 PLACE wolf;   // 狼的状态
 PLACE sheep;  // 羊有状态
 PLACE menu;   // 菜的状态
} STATUS;


const STATUS  c_start = {NO,NO,NO,NO};    // 起始状态
const STATUS  c_end = {YES,YES,YES,YES};  // 终止状态

// 结点(保存转换路径)
typedef struct TURN{
 STATUS   status;
 TURN*    p;
}TURN;

typedef std::list<TURN>  LIST_TURN;
typedef std::list<TURN*> LIST_NODE;

// 判断两个状态是否一致
bool operator == (const STATUS& sa, const STATUS& sb)
{
 return sa.man == sb.man && sa.wolf == sb.wolf &&
  sa.sheep == sb.sheep && sa.menu == sb.menu;
}

// 查找状态是否已经存在
bool Find(LIST_TURN& ls, const STATUS& s)
{
 LIST_TURN::iterator  it = ls.begin();
 for(;it!=ls.end(); it++)
 {
  if((*it).status==s)
   return true;
 }
 return false;
}

// 状态转换运算
enum OPERATOR
{
 MAN_GO,  // 人过河
 MAN_GO_WITH_WOLF, // 人带狼过河
 MAN_GO_WITH_SHEEP, // 人带羊过河
 MAN_GO_WITH_MENU, // 人带菜过河

 MAN_BACK,  // 人回来
 MAN_BACK_WITH_WOLF, // 人带狼回来
 MAN_BACK_WITH_SHEEP, // 人带羊回来
 MAN_BACK_WITH_MENU, // 人带菜回来

 OP_FIRST = MAN_GO,
 OP_LAST = MAN_BACK_WITH_MENU,
};

// 状态转换
bool StatusTurn(const STATUS& src, OPERATOR op, STATUS& desc)
{
 switch(op)
 {
 case MAN_GO:  // 人过河
  if(src.man == NO) {
   desc = src;
   desc.man = YES;
   return true;
  }
  break;
 case MAN_GO_WITH_WOLF: // 人带狼过河
  if(src.man == NO && src.wolf == NO)
  {
   desc = src;
   desc.man = YES;
   desc.wolf = YES;
   return true;
  }
  break;
 case MAN_GO_WITH_SHEEP: // 人带羊过河
  if(src.man == NO && src.sheep == NO)
  {
   desc = src;
   desc.man = YES;
   desc.sheep = YES;
   return true;
  }
  break;
 case MAN_GO_WITH_MENU: // 人带菜过河
  if(src.man == NO && src.menu == NO)
  {
   desc = src;
   desc.man = YES;
   desc.menu = YES;
   return true;
  }
  break;
 case MAN_BACK:  // 人回来
  if(src.man == YES) {
   desc = src;
   desc.man = NO;
   return true;
  }
  break;
 case MAN_BACK_WITH_WOLF: // 人带狼回来
  if(src.man == YES && src.wolf == YES) {
   desc = src;
   desc.man = NO;
   desc.wolf = NO;
   return true;
  }
  break;
 case MAN_BACK_WITH_SHEEP: // 人带羊回来
  if(src.man == YES && src.sheep == YES) {
   desc = src;
   desc.man = NO;
   desc.sheep = NO;
   return true;
  }
  break;
 case MAN_BACK_WITH_MENU: // 人带菜回来
  if(src.man == YES && src.menu == YES) {
   desc = src;
   desc.man = NO;
   desc.menu = NO;
   return true;
  }
  break;

 }

 return false;
}

// 状态检测(检测合法的状态)
bool StatusTest(const STATUS& s)
{
 // 人不在的时候,狼会吃羊,羊会吃菜
 if(s.man != NO){
  if(s.wolf == NO && s.sheep == NO || s.sheep == NO && s.menu == NO)
   return false;

 }
 if(s.man != YES){
  if(s.wolf == YES && s.sheep == YES || s.sheep == YES && s.menu == YES)
   return false;
 }

 return true;
}


int main()
{
 LIST_TURN     history;  // 已经搜索过的状态
 LIST_NODE     active;   // 需要搜索的状态

 // 生成起始结点
 TURN turn;
 turn.status = c_start;
 turn.p = 0;
 history.push_back(turn);
 active.push_back(&history.back());

 // 初始化
 bool bFind = false;
 TURN*  pend = 0;

 // 状态转换图搜索(广度优先,求转换次数最少的路径)
 while(!active.empty())
 {
  // 待搜索的当前结点
  TURN*  pact = active.front();
  active.pop_front();

  // 如果等于终止状态,则搜索成功
  if(pact->status == c_end)
  {
   bFind = true;
   pend = pact;
   break;
  }

  // 计算当前状态的所有可能的下一个状态
  for(OPERATOR op = OP_FIRST; op <= OP_LAST; op=(OPERATOR)(op+1))
  {
   TURN  next;
   // 下一个状态满足:
   // (1) 有一个转换运算从当前状态转换到此状态
   // (2) 此状态是有效的状态
   // (3) 此状态是一个新状态.已经搜索过的状态不用再搜索
   if(StatusTurn(pact->status, op, next.status) &&
    StatusTest(next.status) && !Find(history,  next.status))
   {
    // 为搜索图添加下一个结点
    next.p = pact;
    history.push_back(next);
    active.push_back(&history.back());
   }
  }
 }

 // 如果找到
 if(bFind)
 {
  // 计算路径
  active.clear();
  TURN* p = pend;
  while(p)
  {
   active.push_front(p);
   p = p->p;
  }

  // show node
  for(LIST_NODE::iterator it = active.begin(); it != active.end(); it++)
  {
   if((*it)->status.man == NO) std::cout << "[人]"; else std::cout << "[..]";
   if((*it)->status.wolf == NO) std::cout << "[狼]"; else std::cout << "[..]";
   if((*it)->status.sheep == NO) std::cout << "[羊]"; else std::cout << "[..]";
   if((*it)->status.menu == NO) std::cout << "[菜]"; else std::cout << "[..]";
   std::cout << " <=====> ";
   if((*it)->status.man == YES) std::cout << "[人]"; else std::cout << "[..]";
   if((*it)->status.wolf == YES) std::cout << "[狼]"; else std::cout << "[..]";
   if((*it)->status.sheep == YES) std::cout << "[羊]"; else std::cout << "[..]";
   if((*it)->status.menu == YES) std::cout << "[菜]"; else std::cout << "[..]";

   std::cout << std::endl;
  }
 }
 else
 {
  std::cout<<"Not Found!" << std::endl;
 }

 return 0;
}





相关文章

相关软件