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

来源:互联网 发布:大数据投资 编辑:程序博客网 时间:2024/05/05 07:27
有一个人,一只羊,一只狼,一捆菜(狼可以吃羊,羊可以吃菜,只有人在的情况,才避免吃的情况),准备过河。有一条船只能载两样东西过河(人也算是一样东西,只有人才会往返坐船,其它不会),如何过才会全部安全过河(没有吃的现象)?
分析:可用自动机方法来解决,一个状态可形式化表示为<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;}


                                             
0 0