C++基于人工智能搜索策略解决农夫过河问题示例

本文实例讲述了C++基于人工智能搜索策略解决农夫过河问题。分享给大家供大家参考,具体如下:

问题描述

一农夫带着一头狼,一只羊和一个白菜过河,小船只能一次装载农夫和一样货物,狼会吃羊,羊会吃白菜,只有农夫在时才安全。现欲让所有物品包括农夫都安全过道河对岸,求最佳答案。

状态空间

用16*4的矩阵:a[16][4],存放每一步的状态,第一列表示农夫的状态,第二列表示菜的状态,第三列表示羊的状态,第四列表示狐狸的状态,数组a里面的元素只为0或1,0代表在左岸,1代表在右岸。

初始状态a[0][0]=a[0][1]=a[0][2]=a[0][3]=0,目标状态是矩阵的某一行全为1。

操作规则

1. 农夫做往返运动,即第i步中,a[i][0] = i%2。
2. 每次农夫过河,可以选择带一件货物,也可以选择不带。
3. 在农夫不在场的情况下,狼和羊不能在一起,羊和白菜不能在一起。

搜索策略

为了避免重复,我们将搜索过的状态放到set中,之后避开搜索这个状态即可。

我们使用深度优先搜索。搜索过程为:农夫做往返运动,当农夫从左岸到右岸时,优先选择带货物过河,当农夫从右岸到左岸时,优先选择不带货物过河。做出选择之后,前进一步,看看是否达到目标状态,如果没有达到,则农夫继续往返,知道搜索到目标状态,或者找不到解为止。

C++代码实现

#include <iostream>
#include <cstring>
#include <string>
#include <set>
using namespace std;
void search(int i);
int a[16][4];
set<int> s;
int b[16];
string ss[2];
string t[4];
int k;
int level;
int count1(int a[])//将当前状态转化为10进制数
{
  return a[0]*8+a[1]*4+a[2]*2+a[3];
}
void show(int a[])//显示结果函数
{
  cout<<"      左边:";
  for(int i=1;i<=3;i++)
    if(a[i]==0)
      cout<<t[i]<<" ";
  cout<<"  ";
  cout<<"右边:";
  for(int i=1;i<=3;i++)
    if(a[i]==1)
      cout<<t[i]<<" ";
  cout<<endl<<endl;
}
void bringSomething(int i)//假设农夫会带走某个东西
{
  for(int j=1;j<=3;j++)
  {
    if(a[i][j]==a[i][0])//若j原来和农夫同一个位置,则农夫有可能将j带走。
    {
      a[i+1][j]=a[i+1][0];//假设将j带走
      if((!(a[i+1][1]==a[i+1][2]&&a[i+1][1]!=a[i+1][0]||a[i+1][3]==a[i+1][2]&&a[i+1][2]!=a[i+1][0]))&&s.count(count1(a[i+1]))==0&&i>=level)//第i+1层将j带走时满足条件,则继续搜索第i+1层
      {
        s.insert(count1(a[i+1]));
        b[i]=1;
        cout<<ss[a[i][0]]<<t[j]<<"  ";
        show(a[i+1]);
        level++;
        search(i+1);
      }
      else //若不满足条件则恢复
      {
        a[i+1][j]=a[i][j];
      }
    }
  }
}
void bringNothing(int i)//假设农夫什么也不带走
{
  if((!(a[i+1][1]==a[i+1][2]&&a[i+1][1]!=a[i+1][0]||a[i+1][3]==a[i+1][2]&&a[i+1][2]!=a[i+1][0]))&&s.count(count1(a[i+1]))==0&&i>=level)
  {
    if(i==0)
      cout<<"农夫从左边去右边,什么也不带";
    else
      cout<<"农夫从右边回左边,什么也不带";
    show(a[i+1]);
    s.insert(count1(a[i+1]));
    search(i+1);
    level++;
  }
  else
    b[i]=0;
}
void search(int i)//从第i层开始搜索判断第i+1层可能的情况
{
  if(i>=16||count1(a[i])==15)
    return;
  for(int j=1;j<=3;j++)//用第i层来初始化第i+1层
  {
    a[i+1][j]=a[i][j];
  }
  b[i]=-1;
  if(i%2==1)//在右岸,先考虑农夫什么也不带走
  {
    bringNothing(i);
    if(b[i]==0)
      bringSomething(i);
  }
  else{//在左岸,先考虑农夫会带走某一样东西。
    bringSomething(i);
    if(b[i]!=1)
      bringNothing(i);
  }
}
int main()
{
  ss[0]="农夫从左边去右边,带上";
  ss[1]="农夫从右边回左边,带上";
  t[1]="菜";
  t[2]="羊";
  t[3]="狐狸";
  memset(a,0,sizeof(a));
  for(int i=0;i<16;i++)
  {
    a[i][0]=i%2;
  }
  s.clear();
  k=0;
  level=0;
  s.insert(0);  //先将初始状态储存起来
  search(0); //从第0层开始搜索
  for(int i=0;i<16;i++)
  {
    for(int j=0;j<4;j++)
      cout<<a[i][j]<<" ";
    cout<<endl;
    if(count1(a[i])==15)
      break;
  }
  return 0;
}

结果

农夫从右边回左边,什么也不带 左边:菜 狐狸 右边:羊

农夫从左边去右边,带上菜 左边:狐狸 右边:菜 羊

农夫从右边回左边,带上羊 左边:羊 狐狸 右边:菜

农夫从左边去右边,带上狐狸 左边:羊 右边:菜 狐狸

农夫从右边回左边,什么也不带 左边:羊 右边:菜 狐狸

农夫从左边去右边,带上羊 左边: 右边:菜 羊 狐狸

0 0 0 0
1 0 1 0
0 0 1 0
1 1 1 0
0 1 0 0
1 1 0 1
0 1 0 1
1 1 1 1

希望本文所述对大家C++程序设计有所帮助。

(0)

相关推荐

  • Java矩阵连乘问题(动态规划)算法实例分析

    本文实例讲述了Java矩阵连乘问题(动态规划)算法.分享给大家供大家参考,具体如下: 问题描述:给定n个矩阵:A1,A2,...,An,其中Ai与Ai+1是可乘的,i=1,2...,n-1.确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少.输入数据为矩阵个数和每个矩阵规模,输出结果为计算矩阵连乘积的计算次序和最少数乘次数. 问题解析:由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序.这种计算次序可以用加括号的方式来确定.若一个矩阵连乘积的计算次序完全确

  • Java算法之最长公共子序列问题(LCS)实例分析

    本文实例讲述了Java算法之最长公共子序列问题(LCS).分享给大家供大家参考,具体如下: 问题描述:一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X= { x1, x2,-, xm},则另一序列Z= {z1, z2,-, zk}是X的子序列是指存在一个严格递增的下标序列 {i1, i2,-, ik},使得对于所有j=1,2,-,k有 Xij=Zj.例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,

  • Java实现的猴子吃桃问题算法示例

    本文实例讲述了Java实现的猴子吃桃问题算法.分享给大家供大家参考,具体如下: 猴子吃桃问题 概述:猴子第一天摘下N个桃子,当时就吃了一半,还不过瘾,就又吃了一个:第二天又将剩下的桃子吃掉了一半,又多吃了一个:以后每天都吃前一天身下的一半零一个,到第n天再想吃的时候就只剩下一个桃子了,求第一天共摘了多少个桃子? 思路及演算步骤(求出共摘多少桃子的函数表达式): 离现在的天数作为变量 f(1) = 1 (剩下桃子的数目) f(2) = f(3) - (吃掉了一些) =   f(3) -(f(3)/

  • Java递归算法经典实例(经典兔子问题)

    题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总对数:假设将兔子分为小中大三种,兔子从出生后三个月后每个月就会生出一对兔子, 那么我们假定第一个月的兔子为小兔子,第二个月为中兔子,第三个月之后就为大兔子,那么第一个月分别有1.0.0,第二个月分别为0.1.0, 第三个月分别为1.0.1,第四个月分别为,1.1.1,第五个月分别为2.1.2,第六个月分别为3.2.3,第

  • Java基于循环递归回溯实现八皇后问题算法示例

    本文实例讲述了Java基于循环递归回溯实现八皇后问题.分享给大家供大家参考,具体如下: 运行效果图如下: 棋盘接口 /** * 棋盘接口 * @author Administrator * */ public interface Piece { abstract boolean isRow(int line); abstract boolean isCol(int line,int col); } 棋盘类: /** * 棋盘 * @author Administrator * */ public

  • Java基于递归解决全排列问题算法示例

    本文实例讲述了Java基于递归解决全排列问题算法.分享给大家供大家参考,具体如下: 排列问题 设R={r1,r2,...,rn}是要进行排列的n个元素,Ri=R-{ri}.集合x中元素的全排列记为Perm(X).(ri)Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列.R的全排列可归纳如下: 当n=1时,Perm(R)=(r),其中r是集合中唯一的元素: 当n>1时,Perm(R)由(r1)Perm(R1),(r2)Perm(R2),(r3)Perm(R3)....(

  • Java基于分治算法实现的棋盘覆盖问题示例

    本文实例讲述了Java基于分治算法实现的棋盘覆盖问题.分享给大家供大家参考,具体如下: 在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖.四个L型骨牌如下图: 棋盘中的特殊方格如图: 实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k - 1) * 2^(k - 1)的子棋盘,特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方格不

  • 基于C++的农夫过河问题算法设计与实现方法

    本文实例讲述了基于C++的农夫过河问题算法设计与实现方法.分享给大家供大家参考,具体如下: 问题描述: 一个农夫带着-只狼.一只羊和-棵白菜,身处河的南岸.他要把这些东西全部运到北岸.他面前只有一条小船,船只能容下他和-件物品,另外只有农夫才能撑船.如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜.请求出农夫将所有的东西运过河的方案. 实现上述求解的搜索过程可以采用两种不同的策略:一种广度优先搜索,另一种

  • Java数据结构及算法实例:汉诺塔问题 Hanoi

    /** * 汉诺塔大学的时候就学过,但是根本没搞明白,唯一知道的就是要用递归的方法来求解. * 问题描述: * 有三根杆子A,B,C.A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小. * 要求按下列规则将所有圆盘移至C杆: * 1.每次只能移动一个圆盘: * 2.大盘不能叠在小盘上面. * 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆, * 但都必须尊循上述两条规则. * 问:如何移?最少要移动多少次? * 解决方法: * 假设只有2个盘子,柱子分别是A, B, C柱

  • 浅谈java实现背包算法(0-1背包问题)

    0-1背包的问题 背包问题(Knapsack problem)是一种组合优化的NP完全问题.问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高.问题的名称来源于如何选择最合适的物品放置于给定背包中. 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值.则其状态转移方程便是: f[i][v]=max{ f[i-1][v], f

  • Java简单实现农夫过河问题示例

    本文实例讲述了Java简单实现农夫过河问题.分享给大家供大家参考,具体如下: 一.问题描述 老伯伯要带鱼.狗.猫过河到对岸.,有一条船,只能坐一个人,老伯每次只能带一样动物过河,当老伯不在的时侯狗会咬猫,猫会吃鱼.,请问怎么顺序过河呢? 二.实现代码 package demo; import java.util.ArrayList; import java.util.List; public class CrossRiver { List<String> listThis = new Arra

随机推荐