BFS解决八数码问题和狼人过河问题

1、八数码问题

问题描述:

初态:

0    1    2

3    4    5

6    7    8

如何移动交换0的位置达到终态

1    2     3

4    5     6

7    8     0

思路如下:

先将图转换为一个整数

初态:
876543210
终态:
087654321

构造状态的数据结构

struct node{
int x;
int where0;
}

运动规则如下

switch where0:
case0: d,r
case1: d,l,r
case2: d,l
case3: u,d,r
case4: u,d,l,r
case5: u,d,l
case6: u,r
case7: u,l,r
case8: u,l

switch dir:
case u:t=x/10^(where0-3)%10; x=x-10^(where0-3)*t+10^where0*t;
case d:t=x/10^(where0+3)%10; x=x-10^(where0+3)*t+10^where0*t;
case l:t=x/10^(where0-1)%10; x=x-10^(where0-1)*t+10^where0*t;
case r:t=x/10^(where0+1)%10; x=x-10^(where0+1)*t+10^where0*t;

代码:

  1 #include<iostream>
  2 #include<map>
  3 #include<queue>
  4 #include<cstdlib>
  5 using namespace std;
  6
  7 int pow10[10]={1,10,100,1000,10000,100000,
  8 1000000,10000000,100000000,1000000000};
  9
 10 //数据结构
 11 struct node{
 12     int x;//表示当前状态图
 13     int where0;//0的位置
 14     struct node *pre;//父节点
 15 };
 16
 17 //运动规则
 18 node * goAction(node *p,int dir){
 19     int x=p->x,where0=p->where0;
 20     node *ans=(node *)malloc(sizeof(node));
 21     ans->pre=p;
 22     int t;
 23     switch(dir){
 24         case 1://up
 25             t=x/pow10[where0-3]%10;
 26             x=x-pow10[where0-3]*t+pow10[where0]*t;
 27             where0-=3;
 28             break;
 29         case 2://down
 30             t=x/pow10[where0+3]%10;
 31             x=x-pow10[where0+3]*t+pow10[where0]*t;
 32             where0+=3;
 33             break;
 34         case 3://left
 35             t=x/pow10[where0-1]%10;
 36             x=x-pow10[where0-1]*t+pow10[where0]*t;
 37             where0-=1;
 38             break;
 39         case 4://right
 40             t=x/pow10[where0+1]%10;
 41             x=x-pow10[where0+1]*t+pow10[where0]*t;
 42             where0+=1;
 43             break;
 44     }
 45     ans->x=x;
 46     ans->where0=where0;
 47     return ans;
 48 }
 49
 50 queue<node *>nq;//状态队列
 51 map<int,int>nm;//判重
 52
 53 //新节点加入队列
 54 int join(node *a){
 55     if(nm[a->x]==1)//重复节点不加入队列
 56         return 0;
 57     if(a->x==87654321){//抵达终态
 58         cout<<"路径:"<<endl;
 59         node *h=a;
 60         int step=0;
 61         while(h!=NULL)//打印路径和步数
 62         {
 63             cout<<h->x<<"  ";
 64             step++;
 65             h=h->pre;
 66         }
 67         cout<<step<<endl;
 68         return 1;
 69     }
 70     nm[a->x]=1;
 71     nq.push(a);//加入队列
 72     return 0;
 73 }
 74
 75 void fun(){
 76
 77     while(!nq.empty()){
 78         node *p=nq.front();
 79         nq.pop();
 80         switch(p->where0){//运动规则
 81             case 0:
 82                 join(goAction(p,2));
 83                 join(goAction(p,4));
 84                 break;
 85             case 1:
 86                 join(goAction(p,2));
 87                 join(goAction(p,3));
 88                 join(goAction(p,4));
 89                 break;
 90             case 2:
 91                 join(goAction(p,2));
 92                 join(goAction(p,3));
 93                 break;
 94             case 3:
 95                 join(goAction(p,1));
 96                 join(goAction(p,2));
 97                 join(goAction(p,4));
 98                 break;
 99             case 4:
100                 join(goAction(p,1));
101                 join(goAction(p,2));
102                 join(goAction(p,3));
103                 join(goAction(p,4));
104                 break;
105             case 5:
106                 join(goAction(p,1));
107                 join(goAction(p,2));
108                 join(goAction(p,3));
109                 break;
110             case 6:
111                 join(goAction(p,1));
112                 join(goAction(p,4));
113                 break;
114             case 7:
115                 join(goAction(p,1));
116                 join(goAction(p,3));
117                 join(goAction(p,4));
118                 break;
119             case 8:
120                 join(goAction(p,1));
121                 join(goAction(p,3));
122                 break;
123
124         }
125
126     }
127
128 }
129
130 int main()
131 {
132     node *begin=(node *)malloc(sizeof(node));//初始状态
133     begin->x=876543210;
134     begin->where0=0;
135     begin->pre=NULL;
136     join(begin);
137     fun();
138
139
140 }

2、狼人过河问题

问题描述:

{wolf,human,boat}
分别代表右岸的狼,人,船的数目

初态:{3,3,1}
终态:{0,0,0}

如何从初态抵达终态

规则:
1、每次过河船上可以一人或两人
switch boat:
case 0:
boat++;
wolf+=1||wolf+=2||human+=1||human+=2||wolf+=1,human+=1;
case 1:
boat--;
wolf-=1||wolf-=2||human-=1||human-=2||wolf-=1,human-=1;
2、两岸的狼不能比人多(人数不为0时)
no1:wolf<0||wolf>3||human<0||human>3||boat<0||boat>1
no2:(human>0&&human<wolf)||((3-human)>0&&(3-human)<(3-wolf))

数据结构

struct node{
int wolf;
int human;
int boat;
struct node *pre;
};

代码:

  1 #include<iostream>
  2 #include<map>
  3 #include<queue>
  4 #include<cstdlib>
  5 #include<String>
  6 using namespace std;
  7
  8 struct node{
  9 int wolf;
 10 int human;
 11 int boat;
 12 struct node *pre;
 13 void init(int a,int b,int c,struct node *p){
 14     this->wolf=a;
 15     this->human=b;
 16     this->boat=c;
 17     this->pre=p;
 18 }
 19
 20 bool operator < (const node x) const{//重载运算符,注意map是基于红黑树实现,每个节点需要具备可比性
 21     int hash1=this->wolf*100+this->human*10+this->boat;
 22     int hash2=x.wolf*100+x.human*10+x.boat;
 23     return hash1<hash2;
 24 }
 25
 26
 27
 28 };
 29
 30 queue<node *>nq;//状态队列
 31 map<node,int>nm;//状态判重
 32
 33 //判断能否加入队列
 34 int join(node *a){
 35     if(nm[*a]==1)
 36         return 0;
 37     int wolf=a->wolf,human=a->human,boat=a->boat;
 38     if(wolf<0||wolf>3||human<0||human>3||boat<0||boat>1)
 39         return 0;
 40     if((human>0&&human<wolf)||((3-human)>0&&(3-human)<(3-wolf)))
 41         return 0;
 42     if(a->wolf==0&&a->human==0&&a->boat==0){//终态
 43         node *h=a;
 44         int step=0;
 45         while(h!=NULL){//打印路径和步数
 46             step++;
 47             cout<<"{ "<<h->wolf<<" , "<<h->human<<" , "<<h->boat<<" }  ";
 48             h=h->pre;
 49         }
 50         cout<<endl;
 51         cout<<step<<endl;
 52         return 1;
 53     }
 54     nm[*a]=1;
 55     nq.push(a);
 56     return 0;
 57 }
 58
 59 //运动规则
 60 void goAction(node *p){
 61     node *a=(node *)malloc(sizeof(node));
 62     node *b=(node *)malloc(sizeof(node));
 63     node *c=(node *)malloc(sizeof(node));
 64     node *d=(node *)malloc(sizeof(node));
 65     node *e=(node *)malloc(sizeof(node));
 66     switch(p->boat){
 67         case 0://注意,不能在case里新建变量
 68
 69             a->init(p->wolf+1,p->human,1,p);
 70             join(a);
 71
 72             b->init(p->wolf+2,p->human,1,p);
 73             join(b);
 74
 75             c->init(p->wolf,p->human+1,1,p);
 76             join(c);
 77
 78             d->init(p->wolf,p->human+2,1,p);
 79             join(d);
 80
 81             e->init(p->wolf+1,p->human+1,1,p);
 82             join(e);
 83             break;
 84         case 1:
 85
 86             a->init(p->wolf-1,p->human,0,p);
 87             join(a);
 88
 89             b->init(p->wolf-2,p->human,0,p);
 90             join(b);
 91
 92             c->init(p->wolf,p->human-1,0,p);
 93             join(c);
 94
 95             d->init(p->wolf,p->human-2,0,p);
 96             join(d);
 97
 98             e->init(p->wolf-1,p->human+1,0,p);
 99             join(e);
100             break;
101     }
102     return;
103 }
104
105
106
107 void fun(){
108     while(!nq.empty()){
109         node *p=nq.front();
110         nq.pop();
111         goAction(p);
112     }
113
114 }
115
116 int main(){
117     node *begin=(node *)malloc(sizeof(node));//初态
118     begin->init(3,3,1,NULL);
119     join(begin);
120     fun();
121
122 }

原文地址:https://www.cnblogs.com/eastblue/p/9821237.html

时间: 2024-10-10 16:42:12

BFS解决八数码问题和狼人过河问题的相关文章

每天刷个算法题20160526:BFS解决八数码问题(九宫格问题)

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524864 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

【算法】BFS+哈希解决八数码问题

15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖"X"; 拼图的目的是安排瓷砖以便它们排序为: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15× 这里唯一合法经营是交流'X'与它共享一个边缘的瓷砖之一.作为一个例子,举动下列顺序解决了一个稍微加扰难题: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6

有很多种方法来解决八数码

AI实验报告,改变了重定向.希望通过翼牛. 我很纳闷ida*然而,如何快速的双搜索.还找到了灵感不在位的基础上A*和Ida*来到慢.特别ida* 搜索31步骤甚至十几秒.我写的代码是有问题?忘记丹尼尔路过指点啊.!! ! 另外声明一下,有些东西也是看网上各路牛人的blog学来的,因为比較杂,再次无法一一列出.总之再次感谢把自己的思考的结果放到网上与大家分享的大牛们.谢谢! 八数码问题 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字.不同棋子上标的数字不同

广度优先搜索解决八数码问题

八数码简介 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字,不同棋子上标的数字不同样.棋盘上另一个空格,与空格相邻的棋子能够移到空格中.要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤.所谓问题的一个状态就是棋子在棋盘上的一种摆法.棋子移动后,状态就会发生改变.解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态. 求解八数码问题要懂得的知识 1.康托展开,八数码在交换的过程

A*算法解决八数码问题

以下内容仅是我个人对八数码问题和A*寻路算法的理解,因为我是菜鸟一个,所以写的比较通俗.  八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤. A*算法: A*算法是一种在静态路网中求解最短路径的有效算法,通俗地讲,它不是像深度优先搜索算法和广度优先搜索算法一样的傻瓜式的埋头

人工智能作业homework2--------A*算法解决八数码

1.启发式搜索算法A 启发式搜索算法A,一般简称为A算法,是一种典型的启发式搜索算法.其基本思想是:定义一个评价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展. 评价函数的形式如下: f(n)=g(n)+h(n) 其中n是被评价的节点. f(n).g(n)和h(n)各自表述什么含义呢?我们先来定义下面几个函数的含义,它们与f(n).g(n)和h(n)的差别是都带有一个"*"号. g*(n):表示从初始节点s到节点n的最短路径的耗散值: h*(n):表示从节点n到目标节点

【BFS】八数码问题

描述 八方块移动游戏要求从一个含 8 个数字(用 1-8 表示)的方块以及一个空格方块(用 0 表示)的 3 × 3 矩阵的起始状态开始,不断移动该空格方块以使其和相邻的方块互换,直至达到所定义的目标状态.空格方块在中间位置时有上.下.左.右 4 个方向可移动,在四个角落上有 2个方向可移动,在其他位置上有 3 个方向可移动.例如,假设一个 3× 3 矩阵的初始状态为: 8 0 3 2 1 4 7 6 5 目标状态为: 1 2 3 8 0 4 7 6 5 则一个合法的移动路径为: 8 0 3 >

【转】A*算法解决八数码问题

from utils import ( PriorityQueue) import copy infinity = float('inf') def best_first_graph_search(problem, f): #定义初始节点 node = Node(problem.initial) node.fvalue=f(node) #如果是最终结果,返回节点 if problem.goal_test(node): return node #frotier是一个顺序队列,从小到大排列,排列比较

八数码问题解析

八数码的问题描述为: 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用-1来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局,找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 解决八数码的方法很多,本文采用1.广度优先搜索的策略,和A星算法两种比较常用的算法思想解决此问题 广度优先搜索的策略一般可以描述为以下过程: 状态空间的一般搜索过程 OPEN表:用于存放刚生成的节点 CLOSE表:用于存放将要扩