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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nifecat/article/details/83212368

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

}

猜你喜欢

转载自blog.csdn.net/nifecat/article/details/83212368