zoukankan      html  css  js  c++  java
  • 野蛮人传教士问题(上)

    高级人工智能布置了这个作业,要求用通用结构P=(D,G) D=(S,S0,A,T) G:S->bool表示

    S表示合法状态集合,S0是初始状态集合,A是动作集合,T是状态动作转化集合即 T属于SXAXS,G是目标状态判断的布尔函数。

    给的是3个野蛮人3个传教士,初步分析可以参见http://www.cnblogs.com/6dan_hust/archive/2010/08/23/1806560.html

    采用的是宽度优先搜索,需要存储中间结点,能返回最优解。

    OK,先上最终代码:

      1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #define X 3 //共有三个传教士
    4 #define Y 3 //共有三个野蛮人
    5 int queue[50][4];
    6 //用于存放搜索结点,queue[][0]是左岸传教士人数
    7 //queue[][1]是左岸野蛮人人数,queue[][2]是左岸船的数目
    8 //queue[][3]用于搜索中的父亲结点序号。
    9 int number=1;
    10
    11 int isSafe(int node[3])
    12 {
    13 if ((node[0]==0||node[0]==X)&&(node[1]>=0)&&(node[1]<=Y))
    14 {
    15 return 1;
    16 }
    17 if ((node[0]==node[1])&&(node[1]>=0)&&(node[1]<=Y))
    18 {
    19 return 1;
    20 }
    21 return 0;
    22 }
    23 int isSuccess(int node[3])
    24 {
    25 if (node[0]==0&&node[1]==0)
    26 {
    27 return 1;
    28 }
    29 else
    30 return 0;
    31 }
    32 int isSame(int node[3],int *tail)
    33 {
    34 int i,last=*tail;
    35 for (i=0;i<last;i++)
    36 {
    37 if (node[0]==queue[i][0]&&node[1]==queue[i][1]&&node[2]==queue[i][2])
    38 {
    39 return 1;
    40 }
    41 }
    42 return 0;
    43 }
    44 int doAction(int *now,int *tail)
    45 {
    46 int node[3];
    47 int nnode[3];
    48 int goright[3][2]={{-2,0},{0,-2},{-1,-1}};
    49 int goleft[5][2]={{1,1},{1,0},{0,1},{2,0},{0,2}};
    50 int i,j;
    51 //first与last记录需要展开的结点
    52 int first=*now;
    53 int last=*tail;
    54 printf("第%d次搜索\n",number);
    55 for (i=first;i<last;i++)
    56 {
    57 //获取当前搜索结点
    58 node[0]=queue[i][0];
    59 node[1]=queue[i][1];
    60 node[2]=queue[i][2];
    61 printf("展开结点queue[%d],%d,%d,%d\n",i,node[0],node[1],node[2]);
    62 if (node[2])//船在左边,过去俩人
    63 {
    64 for (j=0;j<3;j++)//分别考虑可能的三个动作
    65 {
    66 nnode[0]=node[0]+goright[j][0];
    67 nnode[1]=node[1]+goright[j][1];
    68 nnode[2]=0;//船到了右边
    69 if (isSafe(nnode))//如果是安全状态,入队
    70 {
    71 if (!isSame(nnode,tail))//判断与之前展开结点是否相同
    72 {
    73 queue[*tail][0]=nnode[0];
    74 queue[*tail][1]=nnode[1];
    75 queue[*tail][2]=nnode[2];
    76 queue[*tail][3]=i;//记录父结点
    77 (*tail)+=1;//tail指针加1
    78 }
    79 if (isSuccess(nnode))
    80 {
    81 return 1;//tail-1的位置就是最终状态结点
    82 }
    83 }
    84 }
    85 }else{//船在右边,过来一人或俩人
    86 for (j=0;j<5;j++)//分别考虑可能的5个动作
    87 {
    88 nnode[0]=node[0]+goleft[j][0];
    89 nnode[1]=node[1]+goleft[j][1];
    90 nnode[2]=1;//船回到左边
    91 if (isSafe(nnode)&&!isSame(nnode,tail))//如果是安全状态且与之间状态不同 入队
    92 {
    93 queue[*tail][0]=nnode[0];
    94 queue[*tail][1]=nnode[1];
    95 queue[*tail][2]=nnode[2];
    96 queue[*tail][3]=i;//记录父结点
    97 (*tail)+=1;//tail指针加1
    98 }
    99 }
    100 }
    101 (*now)+=1;//now指针加1
    102 }
    103 number++;
    104 return 0;
    105 }
    106
    107 int main()
    108 {
    109 int now=0,tail=1,i;//now指示当前搜索结点
    110 queue[0][0]=X;
    111 queue[0][1]=Y;
    112 queue[0][2]=1;
    113 queue[0][3]=-1;//用于返回搜索路程时,初始结点的标记
    114 while(!doAction(&now,&tail))
    115 {
    116 }
    117 tail-=1;
    118 printf("找到的解为\n");
    119 do
    120 {
    121 printf("%d,%d,%d,%d\n",queue[tail][0],queue[tail][1],queue[tail][2],queue[tail][3]);
    122 tail=queue[tail][3];
    123 } while (queue[tail][3]>=0);
    124 printf("%d,%d,%d,%d\n",queue[0][0],queue[0][1],queue[0][2],queue[0][3]);
    125 return 0;
    126 }

    结果:

    我做的主要工作有:

    1.合法状态检验

    由题意知道,若x>0,则x>y,若x<3,则3-x>3-y。则在3>x>0时有x=y。

    2.动作集优化

    由现实意义可知,在最优解中,从左边到右边的船一定是满载2个人。

    我没有给出严格证明,最近时间比较紧,如果你感兴趣的话,可以试试。

    3.重复状态检验

    由于渡船动作的可逆性,使得动作状态转换图中出现很多环。

    为了提高算法性能,必须进行重复状态搜索检验。


    如果有时间的话我会写 野蛮人传教士问题(下)

    主要考虑一般化的传教士野蛮人问题及性能问题。

    1传教士人数

    2野蛮人人数

    3船数,船载

    4由于目标状态已知,可以采用双向搜索

    5启发式搜索等对一般问题进行性能优化

    6....

  • 相关阅读:
    Sql Server2000里面获得数据库里面所有的用户表名称 和对应表的列名称
    c#开发windows应用程序几个小技巧
    "Unexpected Error 0x8ffe2740 Occurred" Error Message When You Try to Start a Web Site
    注册asp.net到iis
    O/R Mapping 影射文件生成的一点研究(暂时放在这里,实现以后再进行总结)
    WMI使用集锦
    NHibernate快速指南
    项目打包以前需要删除的文件
    Asp.Net 学习资源列表
    精彩Blog
  • 原文地址:https://www.cnblogs.com/2010Freeze/p/2388466.html
Copyright © 2011-2022 走看看