过河问题

探讨了使用C++解决经典过河问题的策略,包括如何避免陷入死循环,通过设置存储方式和使用两个数组来表示河两岸的物品状态。详细解析了代码逻辑,包括危险性判断和物品搬运流程。

题目描述:
某人带了一条狗、一只鸡和一筐菜过河,因船小,每次只能带一样东西过河。若单独留下狗和鸡,则狗会吃鸡;若单独留下鸡和菜,则鸡会吃菜。试问他如何过河?


思路解答:
这个刚开始我尝试运用c++的string+递归来实现该问题,结果发现,陷于了死循环,暂时没有想到修改的好主意,只好用老师给的现成的代码实现了。此处我就发现如何设置一个存储的方式是一个都么重要的事情,老师采用的是两个数组,分别代表河的两岸的物品的情况,并且将数组第一个数num[ 0 ] 设置为存储物品的数量,总共开空间大小为4,即int num[ 4 ],后面三个数字 1 表示存在, 0 表示不存在。后面的事情就好处理了。

  1. 赋初值 int A[ 4 ] = {3,1,1,1},int B[ 4 ] = {0,0,0,0};
  2. 确定两个变量 x 和 y,x代表人带过河的物品序号,y代表人带回来的物品序号。
  3. 循环的判断条件:A[ 0 ] 是否为零,为零时,跳出循环。
  4. 然后x与y的作用还包括由于遵守规则:刚拿回来的不能再拿离开。
  5. 危险性的判断:就是两种组合,利用数字表示即可。

代码实现(直接从老师那拿过来,不太好,我加点注释,?)

#include  "iostream"
using  namespace  std;
int  Danger( int  S[4] )//危险性的判断 
{
	int  d = S[0]*1000+S[1]*100+S[2]*10+S[3];
	if  ( d == 2110 || d == 2011 ) //鸡和菜,狗和鸡的组合不满足 
		return  1;  
	else  
		return  0;
}
char*  Disp( int  x )//数字与符号对应转化 
{
    if  ( x == 1 )  return  "狗";  else  if  ( x == 2 )  return  "鸡";  else  return  "菜";
} 
void  CrossRiver()
{
    int  A[4] = {3, 1, 1, 1}, B[4] = {0};//初始化,开始都在A边 
    int  i, x, y = 0;
    while  ( A[0] )//A数量不为零,即未拿完时 
    {
        if  ( y ) //刚拿回来的加一
        {  
        	A[0]++;  
        	A[y] = 1;  
        } 
        A[0]--;//又拿走的减一 
        x = 0;
        i = 1;//每次从一号拿  
        while  ( ! x )
        {
            while  ( ! A[i] || i == y ) //刚拿回来或者已经拿走的  
   		 i++;
            A[i] = 0;//这次拿走的赋值为零,表示拿走 
            if  ( Danger( A ) )//危险  
            {
		A[i] = 1;//表示不拿目前该物品 
		i++;//再往后找一个 
 	     }  
	     else{//符合拿走的要求时 
                x = i;
                cout << "人带" << Disp( x ) << "过河" << endl << endl;
             } 
        }
        B[0]++;//拿到B边时,B边数量加一 
        B[x] = 1;//拿来的赋值为一,表示存在B边 
        y = 0 ;
        if  ( ! A[0] )  break;//A边拿完了 
        if  ( ! Danger( B ) ) //B边不存在冲突项 
              cout << "人空手回来" << endl << endl;  
        else
        {
             i = 1;//从第一个开始查找 
             while  ( ! y )//找到拿走的那一个物品时就退出循环 
             {
                 while  ( ! B[i] || i == x ) //刚拿来或者已经存在的 
   		      i++;
                 B[0]--;//拿走时,数量减一 
                 B[i] = 0;//表示被拿走 
                 y = i;//拿走的物品编号 
                 cout << "人带" << Disp( y ) << "回来" << endl << endl;
             }
       } 
    }
    return ;
}
int  main()
{
    CrossRiver();
    return  1;
}

实现结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值