农夫过河问题

问题描述

一个农夫带着一头狼、一头羊、一颗白菜过河。他面前只有一条船,只能容纳他和一件物品,只有农夫会划船。如果农夫不在场,狼会吃羊、羊会吃白菜,农夫在场则不会。求将所有物品运到对岸的方案。

解题思路

根据物品的位置定义状态,若在左岸记为1,右岸记为0,于是最终方案就是(1,1,1,1)-->(0,0,0,0)所经过的路径。

1、定义状态

2、列举所有状态(人、狼、羊、菜)

3、删除不合理的状态(狼和羊、羊和菜)

4、连边(模拟一次渡河)

5、寻找路径

寻找(1111)-->(0000)的边,可以用寻路算法如bfs、dfs,如果要求最短路可以用最短路算法如bfs、Dijsktra等,当然这里图很简单,可直接观察出来。

(1111)-->(0101)-->(1101)-->(0001)-->(1011)-->(0010)-->(1010)-->(0000)(两条最短路之一)左岸                                 右岸
1、人  狼  羊 花                           空
2、狼  花                                 人 羊
3、人  狼 花                               羊
4、花                                     人 狼  羊
5、人  羊  花                              狼
6、羊                                     人 花  狼
7、人 羊                                  狼 花
8、空                                     狼 花 人 羊   

传教士与吃人恶魔的问题

问题描述

有三个传教士和三个吃人恶魔要渡过一条河,河中有一条船,只能装下两个人。在任何地方(无论是岸边还是船上),如果吃人恶魔数量多于传教士数量,吃人恶魔就会吃掉传教士。问:怎么才能让这些都安全过河?

解题思路

1、定义状态

2、列举所有状态

3、删除不合理状态

4、连边(模拟依次渡河变化)

5、寻找路径

寻找(33 L 00)-->(00 R 33)的路径

其中一条路径
(33 L 00)-->(31 R 01)-->(32 L 01)-->(30 R 03)-->(31 L 02)-->(11 R 22)-->(22 L 01)-->(02 R 31)-->(03 L 30)-->(01 R 32)-->(02 L 31)-->(00 R 33)
1、两个吃人恶魔过河
2、一个吃人恶魔回来
3、两个吃人恶魔过河
4、一个吃人恶魔回来
5、两个传教士过河
6、一个传教士和一个吃人恶魔回来
7、两个传教士回来
8、一个吃人恶魔回去
9、两个吃人恶魔过河
10、一个吃人恶魔回去
11、两个吃人恶魔过河

四人过桥问题

问题描述

在一个漆黑的夜里,四位旅游者来到一座狭窄而没有护栏的桥边,如果不借助手电筒的话,大家是无论也不敢过去。不幸的是四个人中只有一只手电筒,而桥窄得只够两个人同时通过。如果各自单独过桥得话,四个人所需要的时间分别是1、2、5、10分钟,如果两个人同时过桥,所需要的时间是较慢的那个人单独行动时的时间。问:如何设计一个方案,让四个人尽快过桥。

解题思路

与前面两个相比,这次不仅要求方案,同时要求时间最短。

同样需要定义状态,四个人+手电筒的位置

1、定义状态

2、建图

分为每次通过一个人和每次两个人,都是带权无向边。

(下面只连接了与(01111)的边)

3、寻找最短路

寻找(L 1111)-->(R 0000)的最短路,即最短路算法中(01111)-->(10000)的最短路,以下是利用Dijstra算法的解决方法。

最终答案为(2 + 1 + 10 + 2 + 2) = 17.

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<string>
  4 #include<queue>
  5 #include<algorithm>
  6 using namespace std;
  7
  8 //定义图中结点
  9 struct Node
 10 {
 11     int u, d;            //该节点的编号与距离
 12     bool operator < (const Node x) const
 13     {
 14         return  d > x.d;
 15     }
 16 };
 17
 18 //边结构体的定义
 19 struct Edge
 20 {
 21     int to;
 22     int w;
 23     int next;
 24 };
 25
 26 const int INF = 0x3f3f3f3f;
 27 const int V = 32 + 10;
 28 const int E = 32 * 32 + 10;
 29 int dis[V];            //源到各顶点的最短距离
 30 int vis[V];            //记录是否被收录,用来代替集合S
 31 int head[V];          //head[i]表示顶点i的第一条边的数组下标,"-1"表示顶点i没有边
 32 Edge edge[E];
 33
 34 inline void AddEdge(int a, int b, int w, int id)
 35 {
 36     edge[id].to = b;
 37     edge[id].w = w;
 38     edge[id].next = head[a];
 39     head[a] = id;
 40     return;
 41 }
 42
 43 //s为起点
 44 void Dijsktra(int s)
 45 {
 46     priority_queue<Node>q;            //取出集合T中的最小值
 47     memset(vis, 0, sizeof(vis));
 48     memset(dis, INF, sizeof(dis));
 49
 50     dis[s] = 0;
 51     q.push(Node{ s, dis[s] });
 52     while (!q.empty())
 53     {
 54         Node x = q.top(); q.pop();
 55         int u = x.u;
 56
 57         if (vis[u])    continue;
 58
 59         vis[u] = true;
 60         for (int i = head[u]; i != -1; i = edge[i].next)    //松弛与u直接相邻的顶点
 61         {
 62             int v = edge[i].to;
 63             int w = edge[i].w;
 64             if (!vis[v] && dis[u] + w < dis[v])
 65             {
 66                 dis[v] = dis[u] + w;
 67                 q.push(Node{ v,dis[v] });
 68             }
 69         }
 70     }
 71 }
 72
 73 const int score[] = { 1,2,5,10 };   //每个人单独行动的时间
 74
 75 int main()
 76 {
 77     //建图
 78     memset(head, -1, sizeof(head));
 79     int id = 0;
 80     for (int i = 0; i < (1 << 4); i++)
 81     {
 82         int bits[4];
 83         for (int j = 0; j < 4; j++)  bits[j] = (i >> j) & 1;
 84         //一次走一个人
 85         for (int j = 0; j < 4; j++)  if (bits[j])
 86         {
 87             int tmp = i - (1 << j) + 16;
 88             int w = score[j];
 89             AddEdge(i, tmp, w, id++);
 90             AddEdge(tmp, i, w, id++);
 91         }
 92         //一次走两个人
 93         for(int j = 0;j < 3;j++)
 94             for (int k = j + 1; k < 4; k++)   if (bits[j] && bits[k])
 95             {
 96                 int tmp = i - (1 << j) - (1 << k) + 16;
 97                 int w = max(score[j],score[k]);
 98                 AddEdge(i, tmp, w, id++);
 99                 AddEdge(tmp, i, w, id++);
100             }
101     }
102     Dijsktra(15);
103     printf("%d\n", dis[16]);
104
105     return 0;
106 }

此类问题很多,但大多可用图论的思想做(虽然不一定是速度最快的),后续在补充吧,有问题直接留言!

参考链接:中国大学mooc 刘铎老师  离散数学

转载于:https://www.cnblogs.com/lfri/p/9866992.html

过河问题(图论方法)相关推荐

  1. [ 多智能体网络中的图论方法汉化 ] (一)前言第一章

    前言 能够进行短程通信和本地决策的(相对)廉价的传感和驱动节点的出现,提出了许多关于如何协调和控制这种系统的新的系统级问题.可以说,这一新的研究领域面临的最大挑战是本地交互规则如何导致所需的全局属性, ...

  2. 图论在计算机应用,图像分割的图论方法综述-计算机应用与软件.pdf

    第31卷第9期 计算机应用与软件 Vol31No.9 2014年9月 ComputerApplicationsandSoftware Sep.2014 图像分割的图论方法综述 王 梅 李玉砲 全笑梅 ...

  3. 图论方法在大脑网络中的应用

    网络神经科学是一个蓬勃发展且迅速扩展的领域.从分子到行为尺度的大脑网络的数据的规模和复杂性都在不断增加.这些数据的发展对建模和分析大脑网络数据的合适工具和方法具有强烈的需求,例如由图论提供的工具和方法 ...

  4. 数模国赛备赛(6)数学建模中的图论方法

    图论中的许多问题都是NP问题,目前找不到多项式时间内的解决方法. 涉及图论的数学建模题目 涉及到线路,网点等概念的问题,天生就有了图. 图论的很多问题都可以转化成线性规划问题. 例题引入 灾情巡视问题 ...

  5. JAVA 寻找-人鬼过河游戏的方法

    题目: 有三个人和三只鬼在一条河的一岸,需要过河,河中有一条小船,最多可以同时容纳两位,过河的过程中,河岸的任意一边如果,鬼的数目多于人的数目的时候,鬼就会乘机吃掉人,请用程序找出能使人和鬼都能安全过 ...

  6. 运筹学那些事,专科学生学习运筹学之图论方法,No.7

    文章目录 图的基本概念 树和树的逐步生成法 最小枝杈树问题 最短路线问题 最大流量问题 自考说明 图的基本概念 图的最基本要素是: 点以及点之间的一些连线(简称线或者边) 带箭头的线(有向线) 在图的 ...

  7. 运筹学基础【八】 之 图论方法

    感谢内容提供者:金牛区吴迪软件开发工作室 接上一篇:运筹学基础[七] 之 网络计划技术 文章目录 一.图的基本概念 二.树和树的逐步生成法 三.最小枝杈树 四.最短路线问题 五.最大流量问题 一.图的 ...

  8. 商人渡模型matlab及模型假设,商人过河问题

    商人过河问题 一.三名商人各带一名随从的情况 1. 问题(略) 2. 模型假设 ① 当一边岸满足随从数大于商人数,但商人数为0时仍为一种安全状态: ② 小船至多可容纳2人,且渡河时由随从(或者商人)来 ...

  9. 【转】主要空间数据挖掘方法

    Source: http://jerry429.bokee.com/2993629.html 张新长 马林兵等,<地理信息系统数据库>[M],科学出版社,2005年2月 第二章第二节 空间 ...

最新文章

  1. 使用vue加svg实现流程图代码_京东风格的移动端Vue组件库NutUI2.0来啦
  2. 注解能力ApplicationContext作为 IoC 容器示例
  3. System.Windows.Forms.Timer与System.Timers.Timer的区别
  4. Idea 设置Eclipse快捷键(常用)
  5. redis -- 学习
  6. python字典返回键值对列表_返回列表Python dict dictionaries Python 数据结构——字典 返回列表...
  7. Win10+VSCode搭建opencv+C++环境(2)
  8. python学习之路-1 python简介及安装方法
  9. Exchange 2010 无法删除第一个mailbox
  10. Coinbase与CS: GO比赛组织者BLAST Premier签署赞助协议
  11. Java算法——回溯法
  12. Atitit 网关协议cgi wsgi fcgi fastcgi 目录 1.1. CGI(common gateway unterface) 1 1.2. 2.1 WSGI: 1 1.3. 2.3
  13. win10如何搜索计算机网络ip,win10怎样查看电脑IP地址?,看完就明白了
  14. DB2数据库生成html巡检报告
  15. Nginx从入门到精通(笔记)
  16. 如何持续、正确、安全地把材料性能检测试验做好:“清单革命”读书报告
  17. Handlebars.js使用介绍
  18. .NetCore框架Surging系列(一)介绍
  19. jsp的文件操作(二)
  20. 高颜值 Markdown 编辑器(GitHub 标星 17.5 K)

热门文章

  1. 什么是循环 circular symlinks(循环符号链接)?
  2. 扩散硅压力变送器的工作原理?
  3. 北斗/GPS模块定位精度单位RMS,CEP,Sigma介绍
  4. 正厚知识 | 还记得时代的眼泪熊猫烧香吗?
  5. Kmeans 应用
  6. 机械自动化转行计算机软件,做了五年机械的我,劝你千万别转行!因为····...
  7. android 模拟器 超时,【android】android调用模拟器超时问题
  8. PB(PowerBuilder)如何同消息队列(RabbitMQ)通讯
  9. HTML小游戏17 —— 弗莱迪的物理实验游戏(附完整源码)
  10. Android复制查词功能,有道词典Android 3.6版发布 新增“复制查词”功能