传教士过河问题
来源:互联网 发布:淘宝动态评分能改吗 编辑:程序博客网 时间:2024/05/18 02:36
从前有一条河,河的左岸有m个传教士、m个野人和一艘最多可乘n人的小船。约定左岸,右岸和船上或者没有传教士,或者野人数量不超过传教士,否则野人会把传教士吃掉。搜索可使所有的野人和传教士安全渡到右岸的方案。
在这里给出m=3,c=3,n=2的解析
设置状态变量并确定值域
M为传教士人数,C 为野人人数,B为船数,要求M>=C且M,C<= 3,L表示左岸,R表示右岸。
初始状态 目标状态
L R L R
M 3 0 M 0 3
C 3 0 C 0 3
B 1 0 B 0 1
确定状态组,分别列出初始状态集和目标状态集
用三元组来表示 :(ML , CL , BL)(均为左岸状态)
其中 ,BL ∈{ 0 , 1}
:(3 , 3 , 1) : (0 , 0 , 0)
初始状态表示全部成员在河的的左岸;
目标状态表示全部成员从河的左岸全部渡河完毕。
定义并确定规则集合
仍然以河的左岸为基点来考虑,把船从左岸划向右岸定义为Pij操作。其中,第一下标i表示船载的传教士数,第二下标j表示船载的食人者数;同理,从右岸将船划回左岸称之为Qij操作,下标的定义同前。则共有10种操作,操作集为
F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}
P10 if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )
P01 if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )
P11 if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )
P20 if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )
P02 if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )
Q10 if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )
Q01 if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )
Q11 if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )
Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )
Q02 if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )
画出合理的状态空间图
图1 状态空间图
箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
这里我使用了深度优先的搜索方法。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int BOAT=1; //0表示在右岸,1表示在左岸
int TIMES = 1; //记录总共的步数
int NUM_B; //定义船能乘坐的人数
vector <string> fangwen;
bool SAVE(int ML,int CL,int MR,int CR,int BOAT)
{
char ch[20];
if (CL < 0 || ML < 0 || MR < 0 || CR < 0) return false; //如果一方人数小于0时返回 false
if ((ML&&CL > ML) || (MR&&CR>MR)) return false; //传教士人数小于野人会被吃掉
if ((BOAT == 0 && CL == 0 && ML == 0)) //左岸传教士和野人都为零的时候成功渡河
{
cout <<"第"<< TIMES <<"条路。"<< endl;
sprintf(ch, "0,0,0");
fangwen.push_back(ch); //将路径输出
for (int i = 0; i < fangwen.size(); i++)
{
cout << fangwen[i] << endl;
}
cout << endl << endl << endl;
fangwen.pop_back();
TIMES++;
return true;
}
if (BOAT) sprintf(ch, "%d,%d,1", ML, CL); //记录走过的点
else sprintf(ch, "%d,%d,0", ML, CL); //记录走过的点
for (int i = 0; i < fangwen.size(); i++) //防止在死循环 如(1,1,1)||(1,1,0) 来来去去
{
if (fangwen[i] == ch)
return false;
}
fangwen.push_back(ch);
if (BOAT)
{
/*当船只能乘坐两个人的时候
(SAVE(ML - 2, CL, MR + 2, CR, 1 - BOAT));
(SAVE(ML-1, CL-1, MR+1, CR+1, 1 - BOAT));
(SAVE(ML, CL-2, MR, CR+2, 1 - BOAT));
(SAVE(ML-1, CL, MR+1, CR, 1 - BOAT));
(SAVE(ML, CL-1, MR, CR+1, 1 - BOAT));
*/
for (int a = 0; a <=NUM_B; a++)
{
for (int b = 0; b <=NUM_B - a; b++)
{
if(a>0||b>0) //总要有人开船不是
(SAVE(ML-a, CL - b, MR+a, CR + b, 1 - BOAT));
}
}
}
else
{
/* /*当船只能乘坐两个人的时候
(SAVE(ML, CL+2, MR, CR-2, 1 - BOAT));
(SAVE(ML+1, CL+1, MR-1, CR-1, 1 - BOAT));
(SAVE(ML, CL+1, MR, CR-1, 1 - BOAT));
(SAVE(ML+1, CL, MR-1, CR, 1 - BOAT));
(SAVE(ML+2, CL, MR-2, CR, 1 - BOAT));
*/
for (int a = 0; a <= NUM_B; a++)
{
for (int b = 0; b <= NUM_B - a; b++)
{
if (a>0 || b>0) //总要有人开船不是
(SAVE(ML + a, CL + b, MR - a, CR - b, 1 - BOAT));
}
}
}
fangwen.pop_back();
return false;
}
int main()
{
string ch;
int M, C;
cout << "请输入传教士的人数:"; cin >> M;
cout << "请输入野人的人数:"; cin >> C;
cout << "请输入船能乘坐的人数:"; cin >> NUM_B;
if (!SAVE(M, C, 0, 0, 1)&&TIMES<=1)
{
cout << "无路可寻!!" << endl;
}
}
- 传教士野人过河问题
- 传教士过河问题
- 传教士 野人 过河问题
- 传教士过河问题
- 野人传教士过河问题
- 传教士过河问题
- 传教士和野人过河问题
- 野人与传教士过河问题
- 传教士野人过河问题---Java版本
- 传教士与野人过河问题(一)
- 传教士与野人过河问题(二)
- Java实现传教士与野人过河问题
- 野人和传教士过河问题的C语言源代码
- 360面试题:传教士和野人过河问题。
- 野人传教士过河 算法
- 野人传教士过河
- 过河问题(牛虎过河、商人仆人过河、农夫妖怪过河、传教士野人过河)(第2届第2题)
- 传教士问题
- matplotlib 绘制动画
- Qt之加载QSS文件
- 面试体记录第六节——(handlerThread、intentservice、view)
- adb 拷贝手机中的文件到电脑
- SpringBoot四大神器之Actuator
- 传教士过河问题
- 40余家服饰品牌撤出京东,折射京东天猫电商第一之争
- SqlServer2000 调用Http接口的存储过程
- 第三周 【项目3
- 64. Minimum Path Sum
- Sublime实现自动排版
- java迭代器并发修改异常说明
- 给定固定长度的字符串,求解按字符字典序排列,该字符串是第几小?
- 浅谈python(一)--初识python