算法谜题系列1 狼羊人问题

Posted 童话的守望者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法谜题系列1 狼羊人问题相关的知识,希望对你有一定的参考价值。

有一个人,一只羊,一只狼,一捆菜(狼可以吃羊,羊可以吃菜,只有人在的情况,才避免吃的情况),准备过河。有一条船只能载两样东西过河(人也算是一样东西,只有人才会往返坐船,其它不会),如何过才会全部安全过河(没有吃的现象)?
分析:可用自动机方法来解决,一个状态可形式化表示为<p,s,w,c>,即people、sheep、wolf、cabbage的四元组,<1,1,1,1>表示最终的状态,<0,0,0,0>表示初始状态;定义动作集<+1,1,0,0>,<+1,0,1,0>,<+1,0,0,1>,<-1,0,0,0>,<-1,-1,0,0>,<-1,0,-1,0>,<-1,0,0,-1>;定义合法状态p=1||p=0&s=1&w=0&c=0||p=0&s=0&w=1;
这样每一个状态在初始状态s0<0,0,0,0>开始,都可以有4个分支,返回时也有4个分支,注意到每个分支不一定是有效的,所以这需要一个可达性检查的过程,主要的思路如下:
1.过河每次对应三个分支,若扩展的状态<p,s,w,c>中有任意一个p,s,w,c大于1的,矛盾。对于返回后的状态,若任意一个p,s,w,c小于0的,也矛盾。
2.扩展后的状态需满足题目限制条件,即<0,1,1,0>,<0,1,1,1>,<0,1,0,1>以及<1,0,0,1>,<1,0,0,0>,<1,0,1,0>(对岸的情况不满足)
遍历过程中要确保nextstate是新状态,这就需要对每个出现过的状态进行记录	. 
#include <iostream>
#include <list>
using namespace std;
typedef struct state
int p;
int s;
int w;
int c;
;

typedef struct pace
state p;
pace* next;
 ;

bool operator == (const state& sa, const state& sb)

 return sa.p == sb.p && sa.s == sb.s &&sa.w == sb.w && sa.c == sb.c;

state operator +(const state& t1,const state& action)

    state sum;
    sum.p=t1.p+action.p;
    sum.s=t1.s+action.s;
    sum.w=t1.w+action.w;
    sum.c=t1.c+action.c;
 return sum;
;
typedef list<state> statelist;//f_state为状态集合
statelist f_state;
statelist h_state;
state init_state=0,0,0,0;
state end_state=1,1,1,1;
state action_go[4]=1,0,0,0,1,1,0,0,1,0,1,0,1,0,0,1;
state action_back[4]=-1,0,0,0,-1,-1,0,0,-1,0,-1,0,-1,0,0,-1;
state invalid_state[6]=0,1,1,1,0,1,1,0,0,1,0,1,1,0,0,0,1,0,0,1,1,0,1,0;

bool isvalid(state& t1)

if(t1.c>=2||t1.p>=2||t1.s>=2||t1.w>=2)
    return false;
if(t1.c<=-1||t1.p<=-1||t1.s<=-1||t1.w<=-1)
return false;
for(int i=0;i<6;i++)
    if(t1==invalid_state[i])
    return false;
 statelist::iterator   it = h_state.begin();
 for(;it!=h_state.end(); it++)
 
  if((*it)==t1)
   return false;
 
 return true;
;
void getnextstate(int step)


    state t1=f_state.back();
   f_state.pop_back();
    if(t1==end_state)
    
    cout<<step<<endl;
     return;
    
    if(step%2==0)

    for(int i=0;i<4;i++)
    
        state nextstate;
        nextstate=t1+action_go[i];
        if(isvalid(nextstate))
        
            cout<<t1.p<<","<<t1.s<<","<<t1.w<<","<<t1.c<<"+"<<action_go[i].p<<","<<action_go[i].s<<","<<action_go[i].w<<","<<action_go[i].c <<"-->"<<nextstate.p<<","<<nextstate.s<<","<<nextstate.w<<","<<nextstate.c<<endl;
            f_state.push_back(nextstate);
            h_state.push_back(nextstate);
			getnextstate(step+1);

        
    

else

for(int i=0;i<4;i++)
    
        state nextstate;
        nextstate=t1+action_back[i];
        if(isvalid(nextstate))
        
			  cout<<t1.p<<","<<t1.s<<","<<t1.w<<","<<t1.c<<action_back[i].p<<","<<action_back[i].s<<","<<action_back[i].w<<","<<action_back[i].c <<"-->"<<nextstate.p<<","<<nextstate.s<<","<<nextstate.w<<","<<nextstate.c <<endl;
            f_state.push_back(nextstate);
            h_state.push_back(nextstate);
			getnextstate(step+1);
        
    




int main()


    f_state.push_back(init_state);
    h_state.push_back(init_state);
    getnextstate(0);
    return 0;



 

以上是关于算法谜题系列1 狼羊人问题的主要内容,如果未能解决你的问题,请参考以下文章

程序员面试为何会考算法 还有“狼羊白菜过河”的问题

算法谜题面试

建议网站练习 C/C++ 算法/谜题 [关闭]

数据结构与算法之深入解析“滑动谜题”的求解思路与算法示例

可怜的牧羊人

算法竞赛入门经典(第二版)3-5谜题UVA277