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();
}