用编程解决过河问题

很久没有做题了,突然很怀念,于是心血来潮,想起了曾经小弟叫我做的这道趣味题,就花了X个小时(此处不好意思打出来,各位脑补吧)的时间,终于解决了它,那种久违的成就感好像又回来了……但是我的方法不是特别好,代码有点长(以我的水平只能这样了)。不过还是打算把它贴出来,纪念一下。

出一道题让大家思考: 有一条河,河边有猎人,狼,一个男人带着两个小孩,还有一个女人带着两个小孩。 条件:
1.如果猎人离开,狼就会吃掉所有人。 2。如果男人离开,女人就会掐死他的小孩,若女人离开,男人也会掐死她的小孩 3.河里有一条船,所有人都在河的一边,船上只能坐两人。(只有猎人,男人,女人会划船;一个小孩算一个人,狼也算一个。) 问:这八人该如何过河?

分析:解这道智力题我并没有用什么特别的算法,所以就算你没学过动态规划、回溯、矩阵也可以求解这道题,因为我用的是最简单粗暴的方法。

首先,开辟一个数组a[8],表示这8个人,这8个人我是规定好顺序的,从下标0到7分别表示猎人、男人、女人、狼、男孩1、男孩2、女孩1、女孩2。数组a存储的是每个人的位置状态,0表示人在此岸,1表示在对岸。同样的,船也要有位置状态,所以我定义了一个变量boat,0表示船在此岸,1表示在对岸。当boat==a[i]时,表示船与该人在同一岸,可以上船。

然后,每一次渡河都需要记录下来。所以,我开辟了两个数组b1[100]和b2[100],存储每一次渡河的两个人是谁(也就是只能等于0~7中的任意一个数字)。

至于代码中的其他变量:count代表第几次渡河;flag代表这种方案渡河是否可行,0表示不可行,1表示可行;judge()方法检验渡河方案。

#include <stdio.h>
#include <stdlib.h>
void judge(int a[],int k,int t);
int flag;
int count=1;
int b1[100],b2[100];
int main()
{
    char *str,*str2;
    int boat=0;
    int a[8];
    int i,j;
    for(i=0;i<8;i++)
    {
        a[i]=0;//一开始每个人都在此岸,所以赋予状态0
    }
    for(i=0;i<100;i++)
    {
        b1[i]=b2[i]=-1;//一开始没有渡河记录,所以都赋予-1
    }
    //暴力循环直至8个人全都渡河
    while(1)
    {
		//i从0遍历到2是因为只有猎人、男人、女人会划船,a[i]表示渡河的其中一个人
        for(i=0;i<3;i++)
        {
            if(a[i]!=boat)//如果a[i]!=boat说明此人和船不在同一岸,不能上船
            {
                continue;
            }
            //a[j]表示渡河的另一个人
            for(j=0;j<8;j++)
            {
                if(a[j]!=boat)
                {
                    continue;
                }
                //两人都上船之后,划到对岸,位置状态改变
                a[i]=a[j]=1-boat;
                //判断这样渡河是否可以,judge()方法会改变flag的值
                judge(a,i,j);
                //flag=0表示渡河失败,两个人要回去,位置状态也要恢复
                if(flag==0)
                {
                    a[i]=a[j]=boat;
                }
                //flag=1表示渡河成功,记录此次渡河的人,并改变船的位置状态
                else if(flag==1)
                {
                    b1[count]=i;
                    b2[count]=j;
                    boat=1-boat;
                    count++:
                    break;
                }
            }
            //跳出外层循环
            if(flag==1)
            {
                break;
            }
        }
        //i=3说明没有人可以划船了,说明之前的渡河有问题,船与人都倒退一次。
        if(i==3)
        {
            b1[count]=b2[count]=-1;
            count--;
            boat=1-boat;
            a[b1[count]]=a[b2[count]]=boat;
            continue;
        }
		
		//判断8人是否全都过河
        for(i=0;i<8;i++)
        {
            if(a[i]==0)
            {
                break;
            }
        }
        if(i==8)
        {
            break;
        }
    }

    for(i=1;i<count;i++)
    {
        switch(b1[i])
        {
            case 0:str="猎人";break;
            case 3:str="狼";break;
            case 1:str="男人";break;
            case 4:str="男1";break;
            case 5:str="男2";break;
            case 2:str="女人";break;
            case 6:str="女1";break;
            case 7:str="女2";break;
            default:break;
        }
        switch(b2[i])
        {
            case 0:str2="猎人";break;
            case 3:str2="狼";break;
            case 1:str2="男人";break;
            case 4:str2="男1";break;
            case 5:str2="男2";break;
            case 2:str2="女人";break;
            case 6:str2="女1";break;
            case 7:str2="女2";break;
            default:break;
        }
        if(b1[i]==b2[i]){
            printf("%s",str);

        }
        else{
            printf("%s,%s",str,str2);
        }
        if(i%2==0)
        {
            printf("回来\n");
        }
        else{
            printf("过河\n");
        }
    }
    printf("Hello world!\n");
    return 0;
}

void judge(int a[],int k,int t)
{
    flag=1;
    int i,j;
    //如果猎人和狼不在同一岸,且有人和狼在同一岸,渡河失败
    if(a[0]!=a[3])
    {
        for(i=1;i<=7;i++)
        {
            if(a[i]==a[3]&&i!=3)
                flag=0;
        }
    }
    //如果男人或者女人不在同一岸,且自己的孩子与对方在同一岸,渡河失败
    if(a[1]!=a[2])
    {
        if(a[6]==a[1]||a[7]==a[1]||a[4]==a[2]||a[5]==a[2])
        {
            flag=0;
        }
    }
    //如果和上一次渡河相同,则失败
    if((b1[count-1]==k&&b2[count-1]==t)||(b1[count-1]==t&&b2[count-1]==k))
    {
        flag=0;
    }
    //如果已经出现过这种渡河方案不可行了,就不能再这样渡河
    if((b1[count]==k&&b2[count]==t)||(b1[count]==t&&b2[count]==k))
    {
        flag=0;
    }
}


在这里插入图片描述

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值