[数学模型]商人怎样安全过河

问题描述

三名商人各带一个随从乘船渡河,一只小船只能容纳两人,由于他们自己划行,随从密约,在和的任一岸,一旦随从的人数比商人多,就杀人越货,但是如何安排乘船的大权安排在商人们的手中,商人们怎样才能安全渡河?

模型假设

我们需要对问题做一些假设:
1. 每个商人和随从都会划船
2. 只有一条船,且每条船上最多只能乘坐两个人
3. 所有商人与随从之间没有矛盾,不会出现两人不愿意坐一条船的现象
4. 船在渡河的过程中不受外界环境的影响

模型构造

记第 k 次过河前此岸的商人数为 xk , 随从数为 yk , k = 1, 2, 3…, xk ,yk = 0, 1, 2, 3

定义状态: 将二维向量 sk = ( xk , yk ) 定义为状态

将安全渡河状态下的状态集合定义为允许状态集合, 记为

S = {(x,y) | x=0,y=0,1,2,3; x=y=1; x=y=2; x=3,y=0,1,2,3}
记第 k 次渡河船上的商人数为 uk , 随从数为 vk

定义决策: 将二维向量 dk = (uk , vk) 定义为决策

允许决策集合 记作

D = {(u,v) | 1 ≤ u+v ≤ 2, u,v = 0,1,2}
因为小船容量为2,所以船上人员不能超过2,而且至少要有一个人划船,由此得到上式。

由我们定义的状态 sk 和决策 dk ,我们可以发现它们之间是存在联系的:

k 为奇数是表示船由此岸划向彼岸,k 为偶数时表示船由彼岸划回此岸

状态 sk 是随着决策 dk 变化的,规律为:

sk+1 = sk + (-1)kdk
我们把上式称为状态转移律,因此渡河方案可以抽象为如下的多步决策模型:

求决策 dk ∈ D(k = 1,2,…,n) , 使状态 sk ∈ S 按照转移率,初始状态 s1 = (3,3) 经有限步 n 到达状态 sn+1 = (0,0)

到这里,整个数学模型就已经非常清晰了,接下来要做的就是求解模型得出结果。

模型求解

使用dfs就可以,网上找的大牛的C++代码,感觉自己水平还是太菜的
https://www.bbsmax.com/A/Gkz1XLbNdR/

#include <cstdio>
#define maxn 101
int num;//number of bus or fol
int graph[maxn*maxn][maxn*maxn];
int state[maxn][maxn];

//when cross river
int c_bus[5] = {2, 1, 0, 1, 0};
int c_fol[5] = {0, 1, 2, 0, 1};
int b_step[maxn*maxn];
int f_step[maxn*maxn];

bool flag = false;
void DFS(int bus, int fol, int step, int dir)
{
    b_step[step] = bus, f_step[step] = fol;
    if(bus == 0 && fol == 0)
    {
        for(int i = 0; i <= step; i++)
        {
            printf("(%d,%d)", b_step[i], f_step[i]);
            if(i != step )
                printf(" -> ");
        }
        printf("\n");
        flag = true;
    }
    int fa = bus * ( num + 1 ) + fol;
    for(int i = 0; i < 5; i++)
    {
        if(dir)
        {
            int b_next = bus - c_bus[i], f_next = fol - c_fol[i];
            if(b_next >= 0 && b_next < num+1 && f_next >= 0 && f_next < num + 1 && state[b_next][f_next])
            {
                int son = b_next * ( num + 1 ) + f_next;
                if(!graph[fa][son] && !graph[son][fa])
                {
                    graph[fa][son] = 1;
                    graph[son][fa] = 1;
                    DFS(b_next, f_next, step + 1, !dir);
                    graph[fa][son] = 0;
                    graph[fa][son] = 0;
                }
            }
        }
        else
        {
            int b_next = bus + c_bus[i], f_next = fol + c_fol[i];
            if(b_next >= 0 && b_next < num + 1 && f_next >= 0 && f_next < num + 1 && state[b_next][f_next])
            {
                int son = b_next * ( num + 1) + f_next;
                if(!graph[fa][son] && !graph[son][fa])
                {
                    graph[fa][son] = 1;
                    graph[son][fa] = 1;
                    DFS(b_next, f_next, step + 1, !dir);
                    graph[fa][son] = 0;
                    graph[fa][son] = 0;
                }
            }
        }
    }
}
int main()
{
    printf("Please input the number of the businessman: ");
    scanf("%d",&num);
    for(int i = 0; i < num + 1; i++)
    {
        state[i][0] = 1;
        state[i][num] = 1;
        state[i][i] = 1;
    }
    DFS(num, num, 0, 1);
    if(!flag)
        printf("they can't cross the river.");
}
  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
过河数学建模问题涉及n个商人和n个随从同时过河的情况。首先,我们需要确定问题的目标和限制条件。 问题目标: 使得所有商人和所有随从都安全过河,且所需的总时间最短。 问题限制条件: 1. 在任何时候,商人和随从的数量必须相等。即商人和随从必须配对过河。 2. 每次过河,船的容量最多为2。即每次最多可有2个人(商人或随从)同时坐船过河。 3. 在任何时候,如果商人的数量小于随从的数量,商人会被随从攻击。反之,如果随从的数量小于商人的数量,随从会被商人攻击。 建模思路: 1. 首先,我们考虑n=1的情况。只有1个商人和1个随从需要过河。他们都可以安全地渡河,总时间为1。 2. 接下来,我们考虑n=2的情况。有2个商人和2个随从需要过河。这种情况下只存在两种渡河方案: a. 商人1和商人2过河商人1返回,随从1和随从2过河商人2返回。 b. 商人1和随从1过河商人1返回,商人1和随从2过河商人1返回。 总时间为4。 3. 对于n>2的情况,我们可以应用递归的思想。假设我们知道n-1个商人和n-1个随从过河所需的最短时间。我们可以考虑以下两种情况: a. 商人1和商人2过河商人1返回,随从n和随从n-1过河商人2返回,商人1和商人n-1过河。 b. 商人1和随从1过河商人1返回,商人1和随从n过河商人1返回,商人1和商人n-1过河。 总时间为2加上n-1个商人和n-1个随从过河所需的最短时间。 综上所述,我们可以通过递归的方式,逐步推导出求解n个商人和n个随从过河问题所需的时间。其,初始条件为n=1时,总时间为1。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值