目录
题目:实验步骤:实现代码:
题目:
有n个牧师和n个野人准备渡河,但只有一条能容纳c个人的小船,为了防止野人侵犯牧师,要求无论在何处,牧师的人数不得少于野人的人数(除非牧师人数为0),且假定野人与牧师都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出小船来回次数最少的最佳方案。
实验步骤:
输入:牧师人数(即野人人数):n;小船一次最多载人量:c。 输出:若问题无解,则显示Failed,否则,显示Successed输出所有可行方案,并标注哪一组是最佳方案。用三元组(X1, X2, X3)表示渡河过程中的状态。并用箭头连接相邻状态以表示迁移过程:初始状态->中间状态->目标状态。 例:当输入n=2,c=2时,输出:221->200->211->010->021->000; 其中:X1表示起始岸上的牧师人数;X2表示起始岸上的野人人数;X3表示小船现在位置(1表示起始岸,0表示目的岸)。 要求:写出算法的设计思想和源程序,并有用户界面实现人机交互(控制台或者窗口都可以),进行输入和输出结果,如: Please input n: 2 Please input c: 2 Optimal Procedure: 221->200->211->010->021->000 Successed or Failed?: Successed
实现代码:
#include
<stdio
.h
>
#include
<iostream
>
#include
<stdlib
.h
>
using namespace std
;
struct State
{
int Lsavage
;
int Lgodfather
;
int Rsavage
;
int Rgodfather
;
int boat
;
};
struct State
*States
= new State[150];
struct routesave
{
int savage
;
int godfather
;
};
struct routesave
* routesaves
= new routesave[150];
int godfather
, savage
, boatnum
;
void init(State
&m
) {
cout
<< "请输入野人和牧师的人数n, 以及船的最大载量c"<<endl
;
int n
, c
;
cin
>> n
>> c
;
m
.Rgodfather
= n
;
m
.Rsavage
= n
;
godfather
= n
, savage
= n
;
boatnum
= c
;
m
.Lgodfather
= m
.Lsavage
= 0;
m
.boat
= 1;
}
void boaloading(int i
, int s
, int g
) {
if (States
[i
].boat
== 0) {
routesaves
[i
].savage
= s
*-1;
routesaves
[i
].godfather
= g
* -1;
States
[i
+ 1].Lsavage
= States
[i
].Lsavage
- s
;
States
[i
+ 1].Lgodfather
= States
[i
].Lgodfather
- g
;
States
[i
+ 1].Rsavage
= States
[i
].Rsavage
+ s
;
States
[i
+ 1].Rgodfather
= States
[i
].Rgodfather
+ g
;
States
[i
+ 1].boat
= 1;
}
else {
routesaves
[i
].savage
= s
;
routesaves
[i
].godfather
= g
;
States
[i
+ 1].Rsavage
= States
[i
].Rsavage
-s
;
States
[i
+ 1].Rgodfather
= States
[i
].Rgodfather
- g
;
States
[i
+ 1].Lsavage
= States
[i
].Lsavage
+ s
;
States
[i
+ 1].Lgodfather
= States
[i
].Lgodfather
+ g
;
States
[i
+ 1].boat
= 0;
}
}
bool
checkState(State m
) {
if (m
.Rgodfather
> 0 && m
.Rgodfather
< m
.Rsavage
)
return false;
if (m
.Lgodfather
> 0 && m
.Lgodfather
< m
.Lsavage
)
return false;
else return true;
}
void showSolution(int i
) {
cout
<< "问题解决,解决路径为:"<<endl
;
for (int c
= 0; c
< i
; c
++) {
if (routesaves
[c
].savage
>= 0)
cout
<< "第" << c
+1 << "步," << routesaves
[c
].savage
<< "个野人和" << routesaves
[c
].godfather
<< "个传教士乘船去左边" << endl
;
else
cout
<< "第" << c
+1 << "步," << routesaves
[c
].savage
* -1 << "个野人和" << routesaves
[c
].godfather
* -1 << "个传教士乘船去有右边"<< endl
;
}
}
void nextstep(int i
) {
int c
;
if (i
>= 150)
{
cout
<<"试探路径过大,无法计算";
exit(0);
}
for (c
= 0; c
< i
; c
++)
{
if (States
[c
].Lsavage
== States
[i
].Lsavage
&& States
[c
].Lgodfather
== States
[i
].Lgodfather
&& States
[c
].Rsavage
== States
[i
].Rsavage
&& States
[c
].Rgodfather
== States
[i
].Rgodfather
&& States
[c
].boat
== States
[i
].boat
)
{
goto a
;
}
}
if (States
[i
].Rsavage
== 0 && States
[i
].Rgodfather
== 0 && States
[i
].boat
== 0) {
showSolution(i
);
exit(0);
}
if (States
[i
].boat
== 1) {
for (int s
= 1; s
<= boatnum
&& s
<=States
[i
].Rsavage
; s
++) {
int g
= 0;
boaloading(i
, s
, g
);
if (checkState(States
[i
+1])) {
nextstep(i
+1);
}
}
for (int g
= 1; g
<= boatnum
&& g
<=States
[i
].Rgodfather
; g
++) {
for (int s
= 0; s
<= boatnum
- g
&& s
<=States
[i
].Rsavage
&& s
<=g
; s
++) {
boaloading(i
, s
, g
);
if (checkState(States
[i
+ 1])) {
nextstep(i
+ 1);
}
}
}
}
if (States
[i
].boat
== 0) {
for (int s
= 1; s
<= boatnum
&& s
<= States
[i
].Lsavage
; s
++) {
int g
= 0;
boaloading(i
, s
, g
);
if (checkState(States
[i
+ 1])) {
nextstep(i
+ 1);
}
}
for (int g
= 1; g
<= boatnum
&& g
<= States
[i
].Lgodfather
; g
++) {
for (int s
= 0; s
<= boatnum
- g
&& s
<= States
[i
].Lsavage
&& s
<= g
; s
++) {
boaloading(i
, s
, g
);
if (checkState(States
[i
+ 1])) {
nextstep(i
+ 1);
}
}
}
}
a
:return;
}
void main() {
init(States
[0]);
nextstep(0);
}
实验结果展示: