问题描述

三名商人各带–个随从乘船渡河,一只小船只能容纳二人,由他们自己划行.随从们密约,在河的任一岸,一旦随从的人数比商人多,就杀人越货.但是如何乘船渡河的大权掌握在商人们手中.商人们怎样才能安全渡河呢?
对于这类智力游戏,经过一番逻辑思索是可以找出解决办法的.这里用数学模型求解,一是为了给出建模的示例,二是因为这类模型可以解决相当广泛的一类问题,比逻辑思索的结果容易推广.

问题分析

问题已经理想化,所以可以抽象成一个多步决策问题,即在往返的过程中都要保证两岸及船上的商人数大于等于随从数。用允许安全状态变量表示岸上的人员状态,允许决策变量表示船上的人员状况,可以找到状态随决策变化的规律,问题转换为在允许状态下的决策达到安全渡河。

建立模型

此处自行参考《数学模型》姜启源第四版的——商人们怎样安全过河的案例

以下给出代码实现的流程图

代码

main.m

%% 商人安全过河问题
close, clear, clc
%% 声明全局变量
% setOfAllowedStates 允许状态集合
% setOfDecisionVariables 允许决策集合
% collectionOfStatusMarkers 状态标记集合
% numberOfBusinessmen 商人的总人数
% numberOfFollowers 随从的总人数
% maximumLoadCapacity 船的最大承载人数
% totalSetOfDecisionVariables 允许决策个数
% totalSetOfAllowedStates 允许状态个数
% 0ollectionOfStatusMarkersBegin 初始编号
% collectionOfStatusMarkersProcess 中间编号
% collectionOfStatusMarkersEnd 终止编号
global setOfAllowedStates setOfDecisionVariables collectionOfStatusMarkers numberOfBusinessmen collectionOfStatusMarkersProcess cnt k;
global collectionOfStatusMarkersBegin collectionOfStatusMarkersEnd numberOfFollowers maximumLoadCapacity totalSetOfDecisionVariables totalSetOfAllowedStates;
setOfAllowedStates = [];
setOfDecisionVariables = [];
totalSetOfDecisionVariables = 0;
totalSetOfAllowedStates = 0; %% 输入
fprintf('输入大于3 3 2时候将不再作图\n')
numberOfBusinessmen = input('请输入商人的人数:');
numberOfFollowers = input('请输入随从的人数:');
maximumLoadCapacity = input('请输入船的最大承载人数:');%% 作图属性
axis([0 numberOfBusinessmen 0 numberOfBusinessmen]);
set(gca, 'XTick', 0 : 1 : numberOfBusinessmen), set(gca, 'YTick', 0 : 1 : numberOfFollowers);
xlabel('此岸商人数'), ylabel('此岸随从数'), title('允许状态集合')
grid on%% 允许状态集合
for businessmen = 0 : numberOfBusinessmenfor followers = 0 : numberOfFollowersif(businessmen == 0 || businessmen == numberOfBusinessmen || (businessmen >= followers && numberOfBusinessmen - businessmen >= numberOfFollowers - followers))totalSetOfAllowedStates = totalSetOfAllowedStates + 1;setOfAllowedStates(totalSetOfAllowedStates, :) = [businessmen, followers];hold onplot(businessmen, followers, 'b*', 'MarkerSize', 10);endend
endsetOfAllowedStates = [setOfAllowedStates, ones(totalSetOfAllowedStates, 1); setOfAllowedStates, zeros(totalSetOfAllowedStates, 1)];
totalSetOfAllowedStates = totalSetOfAllowedStates * 2;
fprintf('共有%d种允许状态\n', totalSetOfAllowedStates)
printfAllowedStates = input('是否打印允许状态集合y/n?','s');
if printfAllowedStates == 'y'fprintf('允许状态集合:')setOfAllowedStates
end
%% 允许决策集合
for businessmen = 0 : numberOfBusinessmenfor followers = 0 : numberOfFollowersif(businessmen + followers >= 1 && businessmen + followers <= maximumLoadCapacity)totalSetOfDecisionVariables = totalSetOfDecisionVariables + 1;setOfDecisionVariables(totalSetOfDecisionVariables, :) = [businessmen, followers];endend
end
fprintf('共%d个允许决策\n',totalSetOfDecisionVariables);
printfDecisionVariables = input('是否打印允许决策集合y/n?','s');
if printfDecisionVariables == 'y'fprintf('允许决策集合:');setOfDecisionVariables
end
%% 状态标记集合
% 初始状态利用哈希表
collectionOfStatusMarkers = zeros(totalSetOfAllowedStates, 1);
collectionOfStatusMarkersBegin = find(ismember(setOfAllowedStates, [numberOfBusinessmen, numberOfBusinessmen, 1], 'rows') == 1); % 初始状态编号
collectionOfStatusMarkersEnd = find(ismember(setOfAllowedStates, [0, 0, 0], 'rows') == 1); % 终止状态编号
cnt = 0;
k = 1;
collectionOfStatusMarkers(collectionOfStatusMarkersBegin) = 1;
collectionOfStatusMarkersProcess(1) = collectionOfStatusMarkersBegin;%% 模拟过河(递归实现)
crossTheRiver(collectionOfStatusMarkersBegin);
if cnt == 0fprintf('This question currently has no answer.\n')
elsefprintf('共有%d个方法\n', cnt)
end

crossTheRiver.m

function crossTheRiver(present)global setOfAllowedStates setOfDecisionVariables collectionOfStatusMarkers collectionOfStatusMarkersProcess k  numberOfBusinessmen;global collectionOfStatusMarkersEnd totalSetOfDecisionVariables cnt;if present == collectionOfStatusMarkersEndprintCurrentResults();if numberOfBusinessmen <= 3plotCurrentResults(cnt + 1);endelsefor i = 1 : totalSetOfDecisionVariablespossible(1, [1 2]) = setOfAllowedStates(present, [1 2]) + ((-1)^(setOfAllowedStates(present, 3))) * setOfDecisionVariables(i, :);possible(1, 3) = 1 - setOfAllowedStates(present, 3);tag = ismember(setOfAllowedStates, possible, 'rows');if sum(tag) == 1next = find(tag == 1);if collectionOfStatusMarkers(next) == 0collectionOfStatusMarkers(next) = 1;k = k + 1;collectionOfStatusMarkersProcess(k) = next;crossTheRiver(next);collectionOfStatusMarkers(next) = 0;k = k - 1;endendendend
end

printCurrentResults.m

function printCurrentResults()global setOfAllowedStates numberOfBusinessmen collectionOfStatusMarkersProcess cnt k numberOfFollowerscnt = cnt + 1;fprintf('方法 %d:\n',cnt);fprintf('\t\t\t\t此\t岸\t\t\t\t\n');fprintf('\t商人数\t\t\t随从数\t\t\t船的位置\n');for i=1:kfprintf('%d:\t %d\t\t\t\t %d',i,setOfAllowedStates(collectionOfStatusMarkersProcess(i),1),setOfAllowedStates(collectionOfStatusMarkersProcess(i),2));if setOfAllowedStates(collectionOfStatusMarkersProcess(i),3)==1 % 船在此岸fprintf('\t\t\t\t\t此岸\n');elsefprintf('\t\t\t\t\t彼岸\n');endendfprintf('\n');
end

plotCurrentResults.m

function plotCurrentResults(cntPicture)global setOfAllowedStates collectionOfStatusMarkersProcess k numberOfBusinessmen numberOfFollowers;figure(cntPicture)axis([0 numberOfBusinessmen 0 numberOfBusinessmen]);set(gca, 'XTick', 0 : 1 : numberOfBusinessmen), set(gca, 'YTick', 0 : 1 : numberOfFollowers);xlabel('此岸商人数'), ylabel('此岸随从数'), title(['方法', num2str(cntPicture)])grid onfor i = 2 : khold onplot([setOfAllowedStates(collectionOfStatusMarkersProcess(i - 1),1), setOfAllowedStates(collectionOfStatusMarkersProcess(i),1)],...[setOfAllowedStates(collectionOfStatusMarkersProcess(i - 1),2), setOfAllowedStates(collectionOfStatusMarkersProcess(i),2)], 'LineWidth',3)pause(0.2)end
end

动态展示


如有错误以及可以改进的地方欢迎在下方评论区留言!

数学建模——商人过河(Matlab)相关推荐

  1. matlab三个商人三个随从,数学建模 商人过河

    数学建模课程作业 论文题目: 对商人过河问题的研究 指导教师:黄光辉 小组成员:黄志宇(20156260)车辆工程04班 牛凯春(20151927)电气工程05 班 文逸楚(20150382)工商管理 ...

  2. 数学建模-商人过河问题

    商人过河问题 1.问题重述 三名商人各带一个随从乘船渡河,一只小船只能容纳二人,由他们自己划行.随从们密约,在河的任一岸,一旦随从的人数比商人多,就杀人越货.但是如何乘船渡河的大权掌握在商人们手中,商 ...

  3. 【数学建模】基于matlab武汉地铁2号线路线地图动态模拟【含Matlab源码 1092期】

    一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数学建模]基于matlab武汉地铁2号线路线地图动态模拟[含Matlab源码 1092期] 点击上面蓝色字体,直接付费下载,即可. 获取代 ...

  4. 【数学建模】基于matlab船舶三自由度MMG模型【含Matlab源码 1925期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数学建模]基于matlab船舶三自由度MMG模型[含Matlab源码 1925期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式 ...

  5. 数学建模专栏 | 开篇:如何备战数学建模竞赛之 MATLAB 编程

    作 者 简 介 卓金武,MathWorks中国高级工程师,教育业务经理,在数据分析.数据挖掘.机器学习.数学建模.量化投资和优化等科学计算方面有多年工作经验,现主要负责MATLAB校园版业务.曾2次获 ...

  6. 【数学建模】基于matlab动态水波仿真【含Matlab源码 2056期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数学建模]基于matlab动态水波仿真[含Matlab源码 2056期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2: 付费 ...

  7. 【数学建模】基于matlab zernike泽尼克多项式仿真【含Matlab源码 1953期】

    一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数学建模]基于matlab zernike泽尼克多项式仿真[含Matlab源码 1953期] 点击上面蓝色字体,直接付费下载,即可. 获取 ...

  8. 【数学建模】基于matlab三维海浪模型仿真【含Matlab源码 1159期】

    一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数学建模]基于matlab三维海浪模型仿真[含Matlab源码 1159期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2: 付 ...

  9. 【数学建模】基于matlab GUI平行停车模拟仿真【含Matlab源码 1877期】

    一.平行停车模拟仿真简介 近年来, 随着我国经济的快速发展, 机动车保有量也迅速增长.截至2012年底, 全国机动车保有量已达2.4亿辆, 城市"停车难"的问题日趋严重.统计结果表 ...

  10. 做数学建模,学matlab还是python?

    大家好,我是北海. 刚开始参与数学建模的同学,往往会面临一个问题:做数模离不开编程,而matlab和python都挺适合做数模的,究竟是学matlab还是python? 本文就给大家分析一下matla ...

最新文章

  1. arr.sort的排序原理
  2. Ubuntu 命令行打开pdf文件和打开命令行当前目录
  3. c 多文件全局变量_C语言开发单片机为啥都是全局变量形式?
  4. 什么是计算机独立显卡,独立显卡是什么
  5. OpenCASCADE:Modeling Algorithms模块之拓扑工具
  6. python对数的格式_python的log使用详解
  7. Toast源码深度分析
  8. PyTorch官方教程中文版:入门强化教程代码学习
  9. 阿里P8架构师谈:Docker简介、组成架构、使用步骤、以及生态产品
  10. 需求分析师的基本功:逻辑思维、逻辑分析与逻辑表达
  11. java中char和string的区别是什么
  12. [转载] Python学习系列之下划线与变量命名规则
  13. 反编译工具Luyten地址
  14. MATLAB在线网页链接使用
  15. java linux 写文件_Java读写文件
  16. 红队常用的防守策略.
  17. Execel 中文转拼音英文字母
  18. 系统介绍一部手机开发的全流程
  19. 第十三届 蓝桥杯青少年创意编程 C++组 省赛
  20. 沈阳城市学院计算机,喜讯:沈阳城市学院21个代表队在2019全国计算机大赛中全部获奖...

热门文章

  1. win10背景显示计算机名,如何自定义Win10计算机的开始菜单背景和图片
  2. 警方耗时19天抓捕了摄像头破解软件黑产,但你还要知道这些才能放心
  3. 从Python.org下载Python安装包下载很慢
  4. scholarscope不显示影响因子_一劳永逸:这两个查看影响因子的插件你安装了吗?...
  5. 桌球小游戏(java)编程
  6. java基础学习的心得体会
  7. linux下驱动程序数字签名,64位Windows操作系统为驱动程序添加测试数字签名
  8. 惊!我竟然破解了Ta的交换机/路由器的登录密码
  9. 基本music matlab,求利用MUSIC算法进行DOA估计的Matlab源程序
  10. ftell函数使用注意事项