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;
程式碼:
#include<iostream> #include<map> #include<queue> #include<cstdlib> using namespace std; int pow10[10]={1,10,100,1000,10000,100000, 1000000,10000000,100000000,1000000000}; //資料結構 struct node{ int x;//表示當前狀態圖 int where0;//0的位置 struct node *pre;//父節點 }; //運動規則 node * goAction(node *p,int dir){ int x=p->x,where0=p->where0; node *ans=(node *)malloc(sizeof(node)); ans->pre=p; int t; switch(dir){ case 1://up t=x/pow10[where0-3]%10; x=x-pow10[where0-3]*t+pow10[where0]*t; where0-=3; break; case 2://down t=x/pow10[where0+3]%10; x=x-pow10[where0+3]*t+pow10[where0]*t; where0+=3; break; case 3://left t=x/pow10[where0-1]%10; x=x-pow10[where0-1]*t+pow10[where0]*t; where0-=1; break; case 4://right t=x/pow10[where0+1]%10; x=x-pow10[where0+1]*t+pow10[where0]*t; where0+=1; break; } ans->x=x; ans->where0=where0; return ans; } queue<node *>nq;//狀態佇列 map<int,int>nm;//判重 //新節點加入佇列 int join(node *a){ if(nm[a->x]==1)//重複節點不加入佇列 return 0; if(a->x==87654321){//抵達終態 cout<<"路徑:"<<endl; node *h=a; int step=0; while(h!=NULL)//列印路徑和步數 { cout<<h->x<<" "; step++; h=h->pre; } cout<<step<<endl; return 1; } nm[a->x]=1; nq.push(a);//加入佇列 return 0; } void fun(){ while(!nq.empty()){ node *p=nq.front(); nq.pop(); switch(p->where0){//運動規則 case 0: join(goAction(p,2)); join(goAction(p,4)); break; case 1: join(goAction(p,2)); join(goAction(p,3)); join(goAction(p,4)); break; case 2: join(goAction(p,2)); join(goAction(p,3)); break; case 3: join(goAction(p,1)); join(goAction(p,2)); join(goAction(p,4)); break; case 4: join(goAction(p,1)); join(goAction(p,2)); join(goAction(p,3)); join(goAction(p,4)); break; case 5: join(goAction(p,1)); join(goAction(p,2)); join(goAction(p,3)); break; case 6: join(goAction(p,1)); join(goAction(p,4)); break; case 7: join(goAction(p,1)); join(goAction(p,3)); join(goAction(p,4)); break; case 8: join(goAction(p,1)); join(goAction(p,3)); break; } } } int main() { node *begin=(node *)malloc(sizeof(node));//初始狀態 begin->x=876543210; begin->where0=0; begin->pre=NULL; join(begin); fun(); }
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; };
程式碼:
#include<iostream>
#include<map>
#include<queue>
#include<cstdlib>
#include<String>
using namespace std;
struct node{
int wolf;
int human;
int boat;
struct node *pre;
void init(int a,int b,int c,struct node *p){
this->wolf=a;
this->human=b;
this->boat=c;
this->pre=p;
}
bool operator < (const node x) const{//過載運算子,注意map是基於紅黑樹實現,每個節點需要具備可比性
int hash1=this->wolf*100+this->human*10+this->boat;
int hash2=x.wolf*100+x.human*10+x.boat;
return hash1<hash2;
}
};
queue<node *>nq;//狀態佇列
map<node,int>nm;//狀態判重
//判斷能否加入佇列
int join(node *a){
if(nm[*a]==1)
return 0;
int wolf=a->wolf,human=a->human,boat=a->boat;
if(wolf<0||wolf>3||human<0||human>3||boat<0||boat>1)
return 0;
if((human>0&&human<wolf)||((3-human)>0&&(3-human)<(3-wolf)))
return 0;
if(a->wolf==0&&a->human==0&&a->boat==0){//終態
node *h=a;
int step=0;
while(h!=NULL){//列印路徑和步數
step++;
cout<<"{ "<<h->wolf<<" , "<<h->human<<" , "<<h->boat<<" } ";
h=h->pre;
}
cout<<endl;
cout<<step<<endl;
return 1;
}
nm[*a]=1;
nq.push(a);
return 0;
}
//運動規則
void goAction(node *p){
node *a=(node *)malloc(sizeof(node));
node *b=(node *)malloc(sizeof(node));
node *c=(node *)malloc(sizeof(node));
node *d=(node *)malloc(sizeof(node));
node *e=(node *)malloc(sizeof(node));
switch(p->boat){
case 0://注意,不能在case裡新建變數
a->init(p->wolf+1,p->human,1,p);
join(a);
b->init(p->wolf+2,p->human,1,p);
join(b);
c->init(p->wolf,p->human+1,1,p);
join(c);
d->init(p->wolf,p->human+2,1,p);
join(d);
e->init(p->wolf+1,p->human+1,1,p);
join(e);
break;
case 1:
a->init(p->wolf-1,p->human,0,p);
join(a);
b->init(p->wolf-2,p->human,0,p);
join(b);
c->init(p->wolf,p->human-1,0,p);
join(c);
d->init(p->wolf,p->human-2,0,p);
join(d);
e->init(p->wolf-1,p->human+1,0,p);
join(e);
break;
}
return;
}
void fun(){
while(!nq.empty()){
node *p=nq.front();
nq.pop();
goAction(p);
}
}
int main(){
node *begin=(node *)malloc(sizeof(node));//初態
begin->init(3,3,1,NULL);
join(begin);
fun();
}