今天偶尔想到了过河问题。记得读小学六年级的时候第一次接触到这个问题--六个老虎过河问题(百度上有详细介绍,本文解决的是一个简单的问题,下一篇文章中将讨论该问题),当时都是从逻辑思维的方法得到正确的解决方法。本文介绍了普遍适用该类问题的方法以及该方法的改进方法,下一篇文章将介绍问题的变型及解法。

向量法(

人、狗、鸡、米过河问题)

问题描述:某人带狗

、鸡、米用船来过河,只有人会划船(好像是废话,后面问题我们还会假设动物也会划船),另外至多还能载一物,当人不在时,狗要吃鸡(有人可能会质疑:狗吃鸡?,但是我看到的是狗和猫都吃小鸡),鸡吃米。问

人、狗、鸡、米怎么过河?

我们用一个向量来表示

人、狗、鸡、米所处的状态,例如:(1 1 1 1)表示

人、狗、鸡、米都在左岸,则对应的(0 0 0 0)表示

人、狗、鸡、米都在右岸。这些向量我们称为状态向量,但是由于问题的条件限制,有些状态是允许的,而有些状态是不允许的,例如(0 1 1 1)表示人不在左岸,显然是不允许的。我们可以穷举出所有允许的状态:

(1 1 1 1)

(0 0 0 0)

(1 1 1 0)

(0 0 0 1)

(1 1 0 1)

(0 0 1 0)

(1 0 1 1)

(0 1 0 0)

(1 0 1 0)

(0 1 0 1)

从上面的允许状态中,我们可以发现规律如下:

当人在时(也就是第一位为1时),不能有相邻的0,例如(1 1 0 0)是不允许的

当人不在时(也就是第一个为0时),不能有相邻的1 ,例如(0 1 1 0)是不允许的

我们将船的一次运载也用向量表示,例如(1 1 0 0)表示人和狗在船上。由于只有人会划船,则允许的运算向量为:

(1 1 0 0)

(1 0 1 0)

(1 0 0 1)

(1 0 0 0)

因此我们可以将一次过河过程看成是一个状态向量与一个运算向量的异或运算(模2加运算:1+1=0 1+0=1 0+0=0)。根据上述的向量法的描述,我们可以将问题简化成:将状态(1 1 1 1)经过奇数次与运算向量运算,变成状态为(0 0 0 0)的状态转移过程。下面是过河的图解过程:

开始状态

船上状态

结果状态

1

(1 1 1 1)

------>

(1 0 1 0)

------>

(0 1 0 1)

2

(0 1 0 1)

------>

(1 0 0 0)

------>

(1 1 0 1)

3

(1 1 0 1)

------>

(1 0 0 1)

------>

(0 1 0 0)

4

(0 1 0 0)

------>

(1 0 1 0)

------>

(1 1 1 0)

5

(1 1 1 0)

------>

(1 1 0 0)

------>

(0 0 1 0)

6

(0 0 1 0)

------>

(1 0 0 0)

------>

(1 0 1 0)

7

(1 0 1 0)

------>

(1 0 1 0)

------>

(0 0 0 0)

奇数次:去河对岸

偶数次:回河这边

注意事项:

在第3次过河时,开始状态为(1 1 0 1),如果船上状态为(1 1 0 0),则结果状态为(0 0 0 1),然后经过船上状态(1 0 0 1),结果状态为(1 0 0 0),然后经过船上状态(1 0 0 0),就可以完成任务(总共5次过河)。但是这里存在问题:当

开始状态为(0 0 0 1),船上状态不可能为(1 0 0 1)。因为开始状态(0 0 0 1)表示只有米在左岸,船上状态(1 0 0 1)表示人和米在船上,这是不可能的!因此船上状态的选择是有限制的。奇数时,开始状态为1的位置,船上对应位置才可以为1;偶数时,开始状态为0的位置,船上对应的位置才可以为0.通俗的说:奇数时,是将有的东西运到河对岸,偶数时,是将河对岸的东西(河这边没有)运到河这边。这些数学的表述可能太麻烦,我举例说明:奇数时,当河这边只有人、狗、米,我们可以从选择人、狗上船或则人、米上船,而不能选择人、鸡上船(鸡在对岸);当偶数次数时,河这边是狗、河对岸则是人、鸡、米,我们可以人、鸡或则人、米回到河这边,而不能选择人、狗过河。

算法实现:

上面的实现可用matlab或则c来实现。若用matlab来实现,则那些状态向量以及状态间的异或运算比较容易表示;若用c来实现,则用时较短。两者的难点在于

注意事项中的船上变量的选取问题。

因此这种方法不适合用计算机实现,在状态变量较少的情况下,我们可以直接用手工进行运算的方法来得到结果(大家可以试试)。

改进型算法

---图论法

算法思路:将10个状态向量用10个点表示,将这10个状态向量分别与可行的运算向量进行运算,如果结果向量仍为允许的状态向量,则两者间连一条线,从而构成了一个图的问题。我们的目标是找到一条可以从状态(1 1 1 1)到状态(0 0 0 0)的通路。下面是我运算得到的图:

注意:图中的标号用于表示对应的状态

具体算法实现如下:

1、Dijkstra算法

#include#define M 20//边数

#define N 10//顶点数

#define MAX 10000

void Dijkstra(int v, int dist[][N],int D[N],int p[N],int s[N]) ;

int flag[N]={0};

int flag1=0;

int flag2=0;

typedef struct

{

int startvex;

int endvex;

int length;

}edge;//边的结构体

edge T[M];

void main()

{

int dist[N][N]={{0,MAX,MAX,MAX,MAX,1,MAX,MAX,MAX,MAX},//图的邻接矩阵

{MAX,0,MAX,MAX,MAX,MAX,1,1,MAX,MAX},

{MAX,MAX,0,MAX,MAX,1,1,MAX,1,MAX},

{MAX,MAX,MAX,0,MAX,MAX,MAX,1,1,MAX},

{MAX,MAX,MAX,MAX,0,MAX,MAX,1,MAX,1},

{1,MAX,1,MAX,MAX,0,MAX,MAX,MAX,MAX},

{MAX,1,1,MAX,MAX,MAX,0,MAX,MAX,MAX},

{MAX,1,MAX,1,1,MAX,MAX,0,MAX,MAX},

{MAX,MAX,1,1,MAX,MAX,MAX,MAX,0,MAX},

{MAX,MAX,MAX,MAX,1,MAX,MAX,MAX,MAX,0}

};

int D[N]={0};

int p[N]={0};

int s[N]={0};

int num=0;

Dijkstra(0,dist,D, p,s) ;//0表示从状态(1111)开始

}

void Dijkstra(int v, int dist[][N],int D[N],int p[N],int s[N])

{ int i, j, k, v1, min, max=10000, pre; /* Max中的值用以表示dist矩阵中的值*/

v1=v;

for( i=0; imax, 以保证值为的的的的顶顶顶顶点点点点也也也也能能能能加加加加入入入入U */

for( j=0; jD[k]+dist[k][j]) ) /* 调整V-U中各顶点的距离值*/

{D[j]=D[k]+dist[k][j];

p[j]=k+1; /* k是j的前趋*/

}

} /* 所有顶点已扩充到U中*/

for( i=0; i

结果显示如下:

从上图的第七行可知,从标号为1的状态到标号为10的状态所要经过的过程为(数组下标是从0开始的):

1---6---3---7---2---8---5---10

2、通过每对顶点之间的最短路径算法实现:

#include#define N 10 //顶点个数

#define MAX 10000

void Floyd(int dist[N][N],int A[N][N],int path[N][N])

{

for(int i=0;i(A[i][k]+dist[k][j]))//方法一:计算每一次矩阵

{

A[i][j]=(A[i][k]+dist[k][j]);

path[i][j]=path[k][j];

}*/

if(A[i][j]>(A[i][k]+A[k][j]))//方法二:计算的幂次矩阵

{

A[i][j]=(A[i][k]+A[k][j]);

path[i][j]=path[k][j];

}

}

}

void main()

{

int dist[N][N]={{0,MAX,MAX,MAX,MAX,1,MAX,MAX,MAX,MAX},//图的邻接矩阵

{MAX,0,MAX,MAX,MAX,MAX,1,1,MAX,MAX},

{MAX,MAX,0,MAX,MAX,1,1,MAX,1,MAX},

{MAX,MAX,MAX,0,MAX,MAX,MAX,1,1,MAX},

{MAX,MAX,MAX,MAX,0,MAX,MAX,1,MAX,1},

{1,MAX,1,MAX,MAX,0,MAX,MAX,MAX,MAX},

{MAX,1,1,MAX,MAX,MAX,0,MAX,MAX,MAX},

{MAX,1,MAX,1,1,MAX,MAX,0,MAX,MAX},

{MAX,MAX,1,1,MAX,MAX,MAX,MAX,0,MAX},

{MAX,MAX,MAX,MAX,1,MAX,MAX,MAX,MAX,0}

};

int A[N][N];

int path[N][N]={0};//给出两顶点间的路径

int pre=0;

for(int i=0;i

结果显示如下:

从上图的最短路径矩阵的第一行第10列可知,从状态1到状态10需要7步,从具体最短路径的第10行可知,

所要经过的过程为:

1---6---3---7---2---8---5---10

两种方法求得的结果相同,我们可以用图形象的表示如下:

通过对比可以发现,图论法实质是在向量法的基础上进行改进的算法,无论是在手动计算还是计算机实现上都比向量法更好。

原文:http://blog.csdn.net/tengweitw/article/details/25296257

作者:nineheadedbird

c/c++语言编程实现人狗鸡和白菜过河问题的求解过程.,【算法编程】过河问题相关推荐

  1. 人狗鸡米安全过河matlab程序,人狗鸡米过河

    1.学校代码: 10128学 号: 6选修课结业论文(题 目:人狗鸡米过河问题学生姓名:武彩学 院:理学院系 别:数学系专 业:信息与计算科学班 级:信计08-1二 一二 年 5月人狗鸡米过河问题一. ...

  2. 人狗鸡米过河问题matlab代码

    这个还是笔者好久之前写的matlab代码,写的不是很好,还请大家多多在指正 clear;clc South(1,:) = [1,1,1,1]; %南岸 North(1,:) = [0,0,0,0]; ...

  3. 面向对象编程引入“人狗大战”小游戏

    转载于:https://www.cnblogs.com/www-qcdwx-com/p/10435310.html

  4. C算法编程题(二)正螺旋

    前言 上一篇<C算法编程题(一)扑克牌发牌> 写东西前总是喜欢吐槽一些东西,还是多啰嗦几句吧,早上看了一篇博文<谈谈外企涨工资那些事>,里面楼主讲到外企公司包含的五类人,其实不 ...

  5. Computer:少儿编程—每个人都应该学习编程,它能教你如何思考—编程入门的简介(编程语言的特点种类开发工具对比人类语言)、编程应用、编程意义之详细攻略

    Computer:少儿编程-每个人都应该学习编程,它能教你如何思考-编程入门的简介(编程语言的特点&种类&开发工具&对比人类语言).编程应用.编程意义之详细攻略 导读:乔布斯说 ...

  6. 智能机器人c语言编程,【图片】教你快速制作一个简单的人工智能机器人(懂编程的人进来看)【科幻吧】_百度贴吧...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 教你快速制作一个简单的人工智能机器人(懂编程的人进来看) 本文我首发于"人工智能吧",叫做<机器人理解人类语言>和< ...

  7. 人猫鸡米过河c语言算法,人猫鸡米过河问题.doc

    重 庆 交 通 大 学 学 生 实 验 报 告 实验课程名称 数学 开课实验室 学 院 院 级 专业班 班 学 生 姓 名 学 号 开 课 时 间 201 至 201 学年第 学期 综合评分依据实验到 ...

  8. 没学过编程可以自学python吗-完全没学过编程的人学习 Python前应该掌握些什么?...

    在众多高大上的自学指导中,尝试做一股清流,把要讲清楚的都讲清楚,除了一堆资料之外,你能在学之前就有一个非常明显的结果倾向. 本文以<小白带你学Python>为内容方向,试图在繁杂的信息里, ...

  9. 为什么C++编程让人觉得那么难学?

    虽然C++的应用领域很广泛,并且C++开发工程师可以获得良好的待遇和发展前景,但是每个人都很清楚C++编程语言很难学.那么为什么C++编程让人觉得那么难学呢? 为什么C++编程让人觉得那么难学? 1. ...

最新文章

  1. 360展示广告智能化演进
  2. python 开发gui浏览器_Python编程之gui程序实现简单文件浏览器代码
  3. 初识Frida--Android逆向之Java层hook (一)
  4. jsp输入限制正则表达式
  5. Character中的奇葩
  6. 【转】一篇比较清晰简单的C++文件操作
  7. PowerBIDeskTop报表元数据批量更新(可用于翻译场景)
  8. html5表白页面3d,七夕节表白3d相册制作(html5+css3)
  9. 基于yolov3和pythorch框架的火焰识别检测算法
  10. 神经网络中的分类器该如何改成生成器?
  11. 回头再说-006 时间音乐
  12. 蓝桥杯2020年第十一届C/C++国赛C组第一题-约数个数
  13. Extendsim 系统仿真的强大工具,多方法论模拟--介绍和试用
  14. 进制转换方法总结——摘自百度
  15. 苹果MacBook Pro笔记本使用U盘重装win10系统教程
  16. 基于STM32WIFI远程监控电压电流表(二)电流检测电路
  17. 在游戏界,就有了些游戏界的理解。不过本文是对某游戏开发商的信
  18. “我去图书馆”公众号代码抢座的实现
  19. Yapi 可视化接口管理平台部署文档
  20. Matplotlib中画图,使用带有边框的条线

热门文章

  1. C++重载之重载左移运算符
  2. CentOS搭建Elasticsearch6.8.0集群
  3. Apple 产品防水能力,IP68 与 IPX4 级
  4. 轻松下载各大视频网站的 .Flv 视频
  5. CGAL笔记之单元格复合体和多面体篇—三维多面体曲面
  6. 网站服务器怎么恢复原来数据库,五步骤完成WordPress网站和数据库备份、搬迁恢复访问...
  7. 浅谈一下学Java和python哪个好(个人观点)
  8. 发布GIF4J破解版
  9. 设有关系模式R(A,B,C,D),F是R上成立的FD集,F={D→A,D→B},试写出关系模式R的候选健
  10. 2022新版苹果影视海螺主题模板M3.1+全解密版