BFS解决八数码问题和狼人过河问题
Posted eastblue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于BFS解决八数码问题和狼人过河问题的主要内容,如果未能解决你的问题,请参考以下文章
每天刷个算法题20160526:BFS解决八数码问题(九宫格问题)