文章目录

  • 一、猴子摘香蕉问题
    • 1、问题描述
    • 2、解题思路
    • 3、实验结果及分析
      • 实验结果一
      • 实验结果二
      • 实验结果三
    • 4、实验结果
    • 5、实验代码
  • 二、传教士(牧师)与野人问题
    • 1、问题描述
    • 2、实验步骤
    • 3、实验要求
    • 4、解题思路
    • 5、实验代码

一、猴子摘香蕉问题

1、问题描述

利用一阶谓词逻辑求解猴子摘香蕉问题:房内有一个猴子,一个箱子,天花板上挂了一串香蕉,其位置如图1所示,猴子为了拿到香蕉,它必须把箱子搬到香蕉下面,然后再爬到箱子上。请定义必要的谓词,列出问题的初始化状态(即下图所示状态),目标状态(猴子拿到了香蕉,站在箱子上,箱子位于位置b)。
(附加:从初始状态到目标状态的谓词演算过程。)

2、解题思路

猴子按照先到箱子所在位置/从箱子上爬下来→把箱子搬到香蕉下面→爬上箱子摘香蕉的逻辑进行着。
所以需要编写四个行动逻辑——走到箱子所在位置、从箱子上爬下来、把箱子搬到香蕉上面、爬上箱子摘香蕉。

使用一个结构定义猴子、箱子、香蕉、相对箱子的位置状态——
猴子在A点则标-1,猴子在B点则标0,猴子在C点则标1
箱子在A点则标-1,箱子在B点则标0,箱子在C点则标1
香蕉在A点则标-1,香蕉在B点则标0,香蕉在C点则标1
猴子爬上箱子则标1,没爬上则标-1

struct State
{int monkey; /*-1:Monkey at A;0: Monkey at B;1:Monkey at C;*/int box;   /*-1:box at A;0:box at B;1:box at C;*/int banana; /*Banana at B,Banana=0*/int monbox; /*-1: monkey on the box;1: monkey  the box;*/
};
struct State States[150];

输入一个初始状态(a, b, c, d)
根据问题,确定终止状态是猴子摘到香蕉{(x,x,x,0)}(x 属于 {0,-1, 1})。

使用递归调用的方式搜索路径,每次递归前先判断当前状态是否与之前的状态重复,若重复则认为形成一个环路,回到上一步寻找其他方式通往新的状态。

3、实验结果及分析

实验结果一


分析:
初始时,猴子站在A位置,箱子在C位置,香蕉在B位置,猴子没有站在箱子上。

猴子摘香蕉的步骤如下:
猴子走去C位置→猴子把箱子从C位置搬到B位置→猴子爬上箱子→猴子摘到香蕉

实验结果二


分析:
初始时,猴子站在A位置,箱子在B位置,香蕉在B位置,猴子没有站在箱子上。

猴子摘香蕉的步骤如下:
猴子走去B位置→猴子爬上箱子→猴子摘到香蕉

实验结果三


分析:
初始时,猴子站在A位置,箱子在A位置,香蕉在B位置,猴子站在箱子上。

猴子摘香蕉的步骤如下:
猴子从箱子上爬下来→猴子把箱子从A位置搬到B位置→猴子爬上箱子→猴子摘到香蕉

4、实验结果

当传教士与野人为五人,船最多允许三人过河时,程序运行结果如下

解的状态迁移图
1、550->441->440->331->330->221->220->111->110->001

2、550->441->440->331->330->221->220->011->110->001

3、550->441->540->331->330->221->220->111->110->001

4、550->441->540->331->330->221->220->011->110->001

5、实验代码

#include "stdafx.h"
#include<string.h>
#include<iostream>
#include <stdio.h>
using namespace std;struct State
{int monkey; /*-1:Monkey at A;0: Monkey at B;1:Monkey at C;*/int box;   /*-1:box at A;0:box at B;1:box at C;*/int banana; /*Banana at B,Banana=0*/int monbox; /*-1: monkey on the box;1: monkey  the box;*/
};
struct State States[150];
char* routesave[150];
/*function monkeygoto,it makes the monkey goto the other place*/
void monkeygoto(int b, int i)
{int a;a = b;if (a == -1){routesave[i] = "Monkey go to A";States[i + 1] = States[i];States[i + 1].monkey = -1;}else if (a == 0){routesave[i] = "Monkey go to B";States[i + 1] = States[i];States[i + 1].monkey = 0;}else if (a == 1){routesave[i] = "Monkey go to C";States[i + 1] = States[i];States[i + 1].monkey = 1;}else{printf("parameter is wrong");}
}
/*end function monkeyygoto*/
/*function movebox,the monkey move the box to the other place*/
void movebox(int a, int i)
{int B;B = a;if (B == -1){routesave[i] = "monkey move box to A";States[i + 1] = States[i];States[i + 1].monkey = -1;States[i + 1].box = -1;}else if (B == 0){routesave[i] = "monkey move box to B";States[i + 1] = States[i];States[i + 1].monkey = 0;States[i + 1].box = 0;}else if (B == 1){routesave[i] = "monkey move box to C";States[i + 1] = States[i];States[i + 1].monkey = 1;States[i + 1].box = 1;}else{printf("parameter is wrong");}
}
/*end function movebox*/
/*function climbonto,the monkey climb onto the box*/
void climbonto(int i)
{routesave[i] = "Monkey climb onto the box";States[i + 1] = States[i];States[i + 1].monbox = 1;
}
/*function climbdown,monkey climb down from the box*/
void climbdown(int i)//如果初始状态猴子在箱子上,则需要爬下来
{routesave[i] = "Monkey climb down from the box";States[i + 1] = States[i];States[i + 1].monbox = -1;
}
/*function reach,if the monkey,box,and banana are at the same place,the monkey reach banana*/
void reach(int i)
{routesave[i] = "Monkey reach the banana";
}
/*output the solution to the problem*/
void showSolution(int i)//打印
{int c;printf("%s \n", "Result to problem:");for (c = 0; c<i + 1; c++){printf("Step %d : %s \n", c + 1, routesave[c]);}printf("\n");
}
/*perform next step*/
void nextStep(int i)
{int c;int j;//超过一定步数,判断为有问题if (i >= 150){printf("%s  \n", "steplength reached 150,have problem ");return;}//判断是否跟之前的状态相同,若相同则可能陷入循环,需要退出for (c = 0; c<i; c++) /*if the current state is same to previous,retrospect*/{if (States[c].monkey == States[i].monkey&&States[c].box == States[i].box&&States[c].banana == States[i].banana&&States[c].monbox == States[i].monbox)return;}//成功拿到香蕉if (States[i].monbox == 1 && States[i].monkey == 0 && States[i].banana == 0 && States[i].box == 0){showSolution(i);exit(0);}j = i + 1;//进行数据更新,用来标记当前是第几个状态if (States[i].monkey == 0)//猴子站在了位置0{if (States[i].box == 0){if (States[i].monbox == -1){climbonto(i);reach(i + 1);nextStep(j);}else{reach(i + 1);nextStep(j);}}else{monkeygoto(States[i].box, i);nextStep(j);movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}}/*end if*/if (States[i].monkey == -1){if (States[i].box == -1){if (States[i].monbox == -1){movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}else{climbdown(i);nextStep(j);movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}}else if (States[i].box == 0){monkeygoto(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}else{monkeygoto(1, i);nextStep(j);movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}}/*end if*/if (States[i].monkey == 1){if (States[i].box == 1){if (States[i].monbox == -1){movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}else{climbdown(i);nextStep(j);movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}}else if (States[i].box == -1){monkeygoto(-1, i);nextStep(j);movebox(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}else{monkeygoto(0, i);nextStep(j);climbonto(i);reach(i + 1);nextStep(j);}}/*end if*/
}/*end nextStep*/
int main()
{States[0].monkey = -1;States[0].box = 1;States[0].banana = 0;States[0].monbox = -1;nextStep(0);
}

二、传教士(牧师)与野人问题

1、问题描述

有n个牧师和n个野人准备渡河,但只有一条能容纳c个人的小船,为了防止野人侵犯牧师,要求无论在何处,牧师的人数不得少于野人的人数(除非牧师人数为0),且假定野人与牧师都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出小船来回次数最少的最佳方案。

2、实验步骤

输入:牧师人数(即野人人数):n;小船一次最多载人量:c。
输出:若问题无解,则显示Failed,否则,显示Successed输出所有可行方案,并标注哪一组是最佳方案。用三元组(X1, X2, X3)表示渡河过程中的状态。并用箭头连接相邻状态以表示迁移过程:初始状态->中间状态->目标状态。

例:当输入n=2,c=2时,输出:221->200->211->010->021->000;
其中:X1表示起始岸上的牧师人数;X2表示起始岸上的野人人数;X3表示小船现在位置(1表示起始岸,0表示目的岸)。

3、实验要求

写出算法的设计思想和源程序,并有用户界面实现人机交互(控制台或者窗口都可以),进行输入和输出结果,如:
Please input n: 2 Please input c: 2
Optimal Procedure: 221->200->211->010->021->000
Successed or Failed?: Successed

4、解题思路

针对“传教士与野人”实验,输入不同的传教士与野人数目,允许过河的最大人数,可以得到不同的结果。在输出所有可行路径之后,输出最优路径,即所花次数最少的结果。
这题使用DFS算法,运用递归来写DFS算法,搜索扫描可能的路径,若可行则打印出来,同时比较当前路径是否比已存储的最短路径短,若是,则当前路径存储为最短路径,若否则跳过。

5、实验代码

// 传教士与野人.cpp
#include <iostream>
using namespace std;
#define maxNum 150
struct op
{int M; //牧师过河人数int C;  //野人过河人数
};
struct State
{int minister;  //起始岸上的牧师人数int savage;      //起始岸上的野人人数int side;        //side=0,船在初始岸,side=1,船在对岸
};int n;        //牧师和野人数目
int c;      //小船最多能载的人数
int op_num; //有多少种过河方式
int min_road=999;//最短路径
struct op opNum[maxNum];
struct State States[maxNum];
struct State StatesMin[maxNum];//安全状态
int isSafe(int i)
{if (States[i].minister == 0 || States[i].minister == n || States[i].minister == States[i].savage)return 1;return 0;
}
//最终目标
int isGoal(int i)
{if (States[i].minister == 0 && States[i].savage == 0)return 1;return 0;
}
//判断是否跟之前的状态重复
int isRepeat(int i)
{for (int j = 0; j < i; j++){if (States[i].minister == States[j].minister&&States[i].savage == States[j].savage&&States[i].side==States[j].side)return 1;}return 0;
}
//可选择的过河方式
void OpNum()
{for(int i=0;i<=c;i++)for (int j = 0; j <= i&&j<=c-i; j++){opNum[op_num].M = i;opNum[op_num++].C = j;}
}
//存储最短的过河方式
void MinWay(int i)
{for (int j = 0; j <= i; j++){StatesMin[j].minister = States[j].minister;StatesMin[j].savage = States[j].savage;StatesMin[j].side = States[j].side;}
}
//打印
void Print(State *state,int i)
{for (int j = 0; j < i; j++){cout << state[j].minister << state[j].savage << state[j].side<<"->";if (j + 1 % 10 == 0)cout << endl;}cout << state[i].minister << state[i].savage << state[i].side <<endl<<endl;
}
//使用dfs遍历寻找解
void nextStep(int i)
{// 递归出口if (isGoal(i)){if (i < min_road){min_road = i;MinWay(i);}cout << "Successed:" << endl;Print(States,i);return;}// 是否安全if (!isSafe(i))return;// 是否重复if (isRepeat(i))return;int j = i + 1;// 起始岸if (States[i].side == 0){for (int k = 0; k < op_num; k++){if (opNum[k].M > States[i].minister || opNum[k].C > States[i].savage)continue;States[j].minister = States[i].minister-opNum[k].M;States[j].savage = States[i].savage - opNum[k].C;States[j].side = 1;nextStep(j);}}else//对岸{for (int k = 0; k < op_num; k++){if (opNum[k].M > (n-States[i].minister) || opNum[k].C > (n-States[i].savage))continue;States[j].minister = States[i].minister+opNum[k].M;States[j].savage = States[i].savage+opNum[k].C;States[j].side = 0;nextStep(j);}}
}int main()
{cout << "Please input n: ";cin >> n;cout << "Please input c: ";cin >> c;States[0].minister = n;States[0].savage = n;States[0].side = 0;OpNum();nextStep(0);if (min_road < 999){cout << "Optimal Procedure:" << endl;Print(StatesMin, min_road);}else{cout << "Fail." << endl;}return 0;
}

【C++】人工智能实验一 猴子摘香蕉/传教士与野人(含完整代码与状态迁移图)相关推荐

  1. Javaweb实验: JSP与Servlet综合案例(含完整代码)

     1 实验目的 1.了解项目开发的基本流程和开发步骤知识 2.掌握项目分析和软件设计的主要步骤 3.回顾掌握JDBC编程的技术和方法 4.掌握JSP·Servlet综合知识和编程方法  2 实验环境 ...

  2. 【SC应用】【人工智能】Java实现猴子摘香蕉,动画显示

    人工智能课程实验一的任务,写出猴子摘香蕉问题的知识表示,并用代码实现推理过程 问题描述 一个房间里,天花板上挂有一串香蕉,有一只猴子可在房间里任意活动(到处走动,推移箱子,攀登箱子等).设房间里还有一 ...

  3. 用python语言实现人工智能猴子摘香蕉的问题_人工智能实验报告大全:猴子摘香蕉问题的VC编程实现等八次.docx...

    人工智能课内实验报告(8次)学 院: 自动化学院 班 级: 智能1501 姓 名: 刘少鹏(34) 学 号: 目 录课内实验1:猴子摘香蕉问题的VC编程实现--------1课内实验2:编程实现简单动 ...

  4. 用python语言实现人工智能猴子摘香蕉的问题_人工智能实验报告大全:猴子摘香蕉问题的VC编程实现等八次 -...

    人工智能课内实验报告 (8次) 学 院:自动化学院 班 级: 智能1501 姓 名: 刘少鹏(34) 学 号:06153034 目 录 课内实验1:猴子摘香蕉问题的VC编程实现????????1 课内 ...

  5. JAVA语言写的人工智能小实验——猴子摘香蕉

    背景简介/问题描述 一个房间里,天花板上挂有一串香蕉,有一只猴子可在房间里任意活动(到处走动,推移箱子,攀登箱子等).设房间里还有一只可被猴子移动的箱子,且猴子登上箱子时才能摘到香蕉,问猴子在某一状态 ...

  6. C#编写简单的人工智能课程的实验-猴子摘香蕉

    1.实验内容 用C#,编写完成了使用者分别输入猴子.香蕉.箱子所在的位置,输出完整的猴子摘香蕉的过程. 2.大致逻辑 首先由使用者输入猴子.箱子和香蕉所在的位置,首先判断猴子和箱子是否在同一位置,若不 ...

  7. 实验1:猴子摘香蕉问题的Python编程实现

    实验目的 (1)熟悉谓词逻辑表示法; (2)掌握人工智能谓词逻辑中的经典例子--猴子摘香蕉问题的编程实现. 实验内容 房子里有一只猴子(即机器人),位于a处.b处上方的天花板上有一串香蕉,猴子想吃,但 ...

  8. 人工智能基础---上机1:猴子摘香蕉

    人工智能基础-上机1:猴子摘香蕉 一.题目 利用一阶谓词逻辑求解猴子摘香蕉问题:房内有一个猴子,一个箱子,天花板上挂了一串香蕉,其位置如图 1 所示,猴子为了拿到香蕉,它必须把箱子搬到香蕉下面,然后再 ...

  9. 人工智能猴子摘香蕉问题

    猴子摘香蕉问题: 一个房间里,天花板上挂有一串香蕉,有一只猴子可在房间里任意活动(到处走动,推移箱子,攀登箱子等).设房间里还有一只可被猴子移动的箱子,且猴子登上箱子时才能摘到香蕉,问猴子在某一状态下 ...

最新文章

  1. C#编程语言之获取文件编码格式(转载)
  2. Gulp新手入门教程
  3. 【linux笔记】CentOs 7配置网络IP
  4. c语言指数怎么表示_Assembly 浮点表示法
  5. python接口自动化测试二十二:文件下载
  6. Kali学习 | 密码攻击:6.10 创建密码字典
  7. 小程序二维码海报生成
  8. python怎么输入一个数-Python中实现输入一个整数的案例
  9. 基本农田卫星地图查询_别被迷惑了,你手机上的北斗导航App和北斗卫星导航没关系...
  10. JS学习之路系列总结三才阵(此文犹如武林之中的易筋经,是你驰骋IT界的武功心法,学会JS五大阵法就学会了JS,博主建议先学三才阵)
  11. **浅谈STM32系列单片机的零基础学习方法**
  12. 【MAC使用技巧】QuickTime Player使用技巧
  13. Idel插件jrebel安装以及破解教程
  14. 【ACWing】1278. 树的统计
  15. 近三年六级作文题目汇总
  16. 【学习OpenCV】warpAffine函数实现图像旋转
  17. 硬件设计之JTAG转USB转换芯片
  18. 读锁有什么用?读为什么要加锁?
  19. 大数据Spark超经典视频链接全集
  20. 分享下个人一直以来整理维护的C++/Qt开发用到的控件库

热门文章

  1. 解锁Bootloader
  2. 如何卸载IE9 再恢复到IE8?
  3. 13.ListView和GridView
  4. directshow 虚拟摄像头 实例 代码解读
  5. Ubuntu与Win10双系统启动界面优化——附Cyberpunk主题下载
  6. 10个最佳iOS Map App模板
  7. 华为安卓手机记事本内容导出
  8. 通过手机记事本发微信是避免出错的好办法
  9. 随笔 | 武汉大学管理课笔记 第一课
  10. java最美验证码_java超简单,超级实用验证码