人工智能实验2 传教士过河问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能实验报告
班级:计研-12班
学号:25
姓名:孔德星
实验二知识表示方法
1.实验目的
(1)了解知识表示相关技术;
(2)掌握问题规约法或者状态空间法的分析方法。
2.实验内容(2个实验内容可以选择1个实现)
(1)梵塔问题实验。
熟悉和掌握问题规约法的原理、实质和规约过程;理解规约图的表示方法;
(2)状态空间法实验。
从前有一条河,河的左岸有m个传教士、m个野人和一艘最多可乘n人的小船。
约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。
搜索一条可使所有的野人和传教士安全渡到右岸的方案。
3.实验报告要求
(1)简述实验原理及方法,并请给出程序设计流程图。
实验原理:假设开始时传教士、野人和船都在右岸,用数组(a,b,c)分别表示右岸传教士个数、右岸野人个数、船的位置,则可分为三种情况讨论:
A、n>m/2。
此种情况下,先把所有的野人度过去,每次返回一个野人,当出现(m,0,0)情况时,返回m-n个野人(若m==n,返回1个野人)。
然后渡n个传教士,此时野人==传教士,然后返回一个野人和传教士,再开始最大限度的渡传教士,每次返回一个野人,最终直到
a==b==c==0;
B、n<=3&&n<=m/2 || n==1,显然此时无解;
C、n>=4&&n<=m/2,此时只能每次传n/2个传教士和野人,每次返回一个野人和传教士,直到最终结果。
程序流程图:
(2)源程序清单:
本程序用C++语言编写。
#include"iostream"
using namespace std;
bool flag = false; //标记是否有解
bool af = false; //标记a是否为0
bool bf = false; //当b变为0后赋值为true;
bool ef = false; //当a==b后赋值为true
bool f = false; //判断n是否大于m/2
int m;//传教士野人的个数
int n;//船一次能装载的人数
void mc(int a,int b,int c);
int main()
{
cout<<"传教士与野人过河问题。
\n假设最初时传教士与野人在河的右岸。
\n";
cout<<"请输入传教士野人的个数:\n";
cin>>m;
cout<<"请输入船一次能装载的人数: \n";
cin>>n;
cout<<"右岸传教士人数\t"<<"右岸野人个数\t"<<"船的位置(1.右岸 0左岸)"<<endl;
if((m<=3 && n<=m/2) || n==1) //此种情况无解
{cout<<"No solution!\n";
system("pause");
return 0; }
if(n > m/2)
f = true;
mc(m,m,1);
if(flag == true){ cout<<"Success!\n"; }
else{ cout<<"No solution!\n"; }
system("pause");
return 0;
}
void mc(int a,int b,int c)
{
if(flag==true) return;
if(c == 1) {
cout<<"\t"<<a<<"\t\t"<<b<<"\t\t"<<c<<"\t\n";
if(f==true) //如果n>m/2
{
if(bf!=true) //b未达到过0
{
if(a+b<=n) //如果a+b<=n,完全渡过
mc(0,0,1-c); //递归
else
{
for(int j = n;j >= 0;j--)
{
if(b >= j)
{
mc(a,b-j,1-c); //递归
if(flag==true)
return;
}
}
}
}
else if(ef!=true&& af==false)
{
for(int i = n;i>=0;i--)
{
if(a>=i)
{
mc(a-i,b,1-c); //递归
if(flag==true) return;
}
}
}
if(ef == true && af==false)
{
if(a>=n)
mc(a-n,b,1-c); //递归
else if(a+b<n)
mc(0,0,1-c);
else
mc(0,b-(n-a),1-c);
}
if(af==true)
{ if(b>=n) mc(a,b-n,1-c); //递归else mc(a,0,1-c); } } else{ mc(a-n/2,b-n/2,1-c); //递归
}
}
if(c == 0)
{
cout<<"\t"<<a<<"\t\t"<<b<<"\t\t"<<c<<"\t\n";
if(a == b && b == c && a == 0)
{
flag = true;
return;
}
if(f==true) //如果n>m/2
{
if(b==0)
{
bf = true;
if(m <= n)
mc(a,b+1,1-c); //递归
else
mc(a,b+m-n,1-c);
}
if(a==b)
{
ef = true;
mc(a+1,b+1,1-c); //递归
}
if(a == 0)
{
af = true;
mc(a,b+1,1-c); //递归
}
while(bf!=true)
{
mc(a,b+1,1-c); //递归
}
}
else//k<=n/2&&k>3
mc(a+1,b+1,1-c); //递归
}
}
(3)实验结果及分析。
程序实验结果如下图。
当然,传教士与野人个数为3,船一次能载两个人,这是最经典的例子。
本程序也可输入其它数据,同样可以得到正确结果。
本程序主要采用状态空间法和递归调用来解决问题。
程序在一开始就排除了不可能会成功的状态空间,也对剩下的状态空间也进行了分类,这样直接减少了问题的复杂程度。
另外,本程序大量采用递归调用的思想,减少了编程代码的工作量,也增加了我对人工智能算法的熟悉度。
本程序基本上达到了实验的最初要求。
不仅如此,通过对本程序的编写,提高了我对人工智能思想的掌握程度和学习兴趣,相信在以后我更会经常地用人工智能的思想去研究算法,编写程序。