野人过河
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程实验报告
1.实验目的
掌握人工智能程序设计语言Prolog描述一般性的实际问题的程序编写方法。
理解通过搜索求解问题实现人工智能的思想。
2.实验要求
要求学生对野人过河以及基本搜索算法有一定的了解
3.实验内容
设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一边河岸上,野人的数量超过传教士,野人就要吃掉传教士,问怎样才能用船将3个传教士和3个野人从左岸都渡到右岸,又不会发生传教士被吃的事件呢?通过Prolog程序,给出乘船过河的动作序列。
理解问题所在,并将该问题抽象为对状态空间的搜索问题。
设计搜索算法,解决该问题。
该问题可以使用自己擅长的计算机语言来解决。
4.实验软硬件环境
基本Windows系统基本运行环境,Visual Prolog;dev c++;
5.实验方案
(1)设置该问题的状态。
例如:((左岸牧师数,左岸野人数),(右岸牧师数,右岸野人数),船的位置)。
(2)定义目标状态。
这里是:((0,0),(3,3),1):((左岸牧师数,左岸野人数),(右岸牧师数,右岸野人数),船的位置)
(3)描述可能的动作。
船上所能够载人的状态就是可能的操作。
用谓词move 表示。
如:move(1,0).表示船上有一位牧师,没有野人。
(4)判断合法状态。
如:legal((X,Y,_)):- %X为左岸状态,Y为右岸状态。
(5)深度优先搜索。
Findroad。
6.实验过程
三个传教士和三个野人的示例程序如下:
move(1,0).
move(0,1).
move(0,2).
move(2,0).
move(1,1).
legal((X,Y,_)):-legal1(X),legal1(Y).
legal1((X,Y)):-X=:=0,Y>=0,!.
legal1((X,Y)):-Y=:=0,X>=0,!.
legal1((X,Y)):-X>=Y,X>=0,Y>=0.
update((X,Y,0),Move,Statu1):-
(A,B)=X,
(C,D)=Y,
(E,F)=Move,
C1 is C+E,
D1 is D+F,
A1 is A-E,
B1 is B-F,
Statu1=((A1,B1),(C1,D1),1). update((X,Y,1),Move,Statu1):- (A,B)=X,
(C,D)=Y,
(E,F)=Move,
C1 is C-E,
D1 is D-F,
A1 is A+E,
B1 is B+F,
Statu1=((A1,B1),(C1,D1),0). connect(Statu,Statu1):-
move(X,Y),
update(Statu,(X,Y),Statu1), legal(Statu1).
findroad(X,X,L,L):-write(L). findroad(X,Y,L,L1):-
connect(X,Z),
not(member(Z,L)),
findroad(Z,Y,[Z|L],L1).
但是在visual prolog上运行不起来。
所以用c++,深度优先算法搜索
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
using namespace std;
bool flag = true; //true:表示在右岸
vector<string> visit; //记录已经访问过的状态
bool dfs( int M, int C, int m, int c){
if( M<0||C<0||m<0||c<0) //非法
return false;
if( (M&&C>M) ||(m&&c>m)) //野人会吃牧师
return false;
if( flag&&M==0&&C==0 ||(!flag&&m==0&&c==0)) //全部运输过去return true;
//检查该节点是否出现过
char s[30];
if( !flag )
sprintf( s, "M=%d,C=%d,m=%d,c=%d,boat=left", M,C,m,c); else
sprintf( s, "M=%d,C=%d,m=%d,c=%d,boat=right", m,c,M,C); string str(s);
for( int i=0; i<visit.size(); i++)
if( visit[i]==str) //该状态已经搜索过了return false;
visit.push_back(str);
flag = !flag;
if( dfs( m+2, c, M-2,C) ){
printf("2,0\n");
printf("%s\n",s);
return true;
}
else if( dfs( m, c+2, M, C-2) ){
printf("0,2\n");
printf("%s\n",s);
return true;
}
else if( dfs( m+1, c+1, M-1, C-1) ){
printf("1,1\n");
printf("%s\n",s);
return true;
}
else if( dfs( m+1, c, M-1, C)){
printf("1,0\n");
printf("%s\n",s);
return true;
}
else if( dfs( m, c+1, M, C-1)){
printf("0,1\n");
printf("%s\n",s);
return true;
}
flag = !flag;
visit.pop_back();
return false;
}
int main(){
char s[30];
int M=3,C=3,m=0,c=0;
sprintf( s, "M=%d,C=%d,m=%d,c=%d,boat=left", M,C,m,c);
printf("%s\n",s);
if(!dfs(M,C,0,0))
cout << "Can not find the solution."<<endl;
return 0;
}
设置初始状态M左岸牧师数量;C左岸野人数量;m右岸牧师数量;c右岸野人数量;船在左岸。
7.实验结果
8.实验心得
对Prolog语言还不太熟悉,在百度搜索和各种尝试之后也还是没能在visual prolog上解决该问题,所以用了c++来解决这个经典的利用深度或广度优先搜索来解决的野人过河问题,以后还要多学习和使用prolog语言解决问题。