BFS/DFS实现狼羊白菜农夫过河问题

BFS

#include<iostream>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<set>
#include<memory.h>
#include<algorithm>
using namespace std;

typedef long long ll;
typedef int ElemType;

string w = "0000";	//人、狼、羊、白菜的初始状态
string state, tmpstate; 

int path[20];	//存路径 

//狼吃羊,羊吃白菜 
bool Judge(string t)
{
	if ((t[0] != t[1] && t[1] == t[2]) || (t[0] != t[2] && t[2] == t[3]))
		return false;
	return true;
}

//由二进制转化为十进制 
int bit(string s)
{
	return ((s[0]-'0')<<3) + ((s[1]-'0')<<2) + ((s[2]-'0')<<1) + (s[3]-'0');
}

void BFS()
{
	memset(path, -1, sizeof(path));
	queue<string> q;	//记录多重选择
	
	//加入初始状态 
	path[0] = 0;
	q.push(w);
	
	int now = 0, tmp = 0;	//当前状态、临时状态	
	
	while (!q.empty() && path[15] == -1)	//如果队列不为空或都没到对岸则继续搜索 
	{
		//出队当前状态 
		state = q.front();	 
		q.pop();
		
		now = bit(state);                              
		//人带其他行动 
		for (int i = 1; i <= 3; ++i)	//分别判断人能否带狼、羊、白菜过河 
		{
			tmpstate = state;
			if(state[0] == state[i])
			{
				(tmpstate[0] == '0') ? (tmpstate[0] = '1', tmpstate[i] = '1') : (tmpstate[0] = '0', tmpstate[i] = '0');
				tmp = bit(tmpstate);
				
				//如果合法且不重复 
				if (Judge(tmpstate) && path[tmp] == -1)
				{
					q.push(tmpstate);
					path[tmp] = now;
				} 
			}
			//人单独行动 
			tmpstate = state;
			tmpstate[0] = (tmpstate[0] == '0' ? '1' : '0');
			tmp = bit(tmpstate);
			if (Judge(tmpstate) && path[tmp] == -1)
			{
				q.push(tmpstate);
				path[tmp] = now;
			} 
		} 
	}
}
 
string BtoS(int t)
{
	string tmp = "";
	while(t)
	{
		tmp += t%2 + '0';
		t /= 2;
	}
	while(tmp.length() < 4)
		tmp += '0';
	return tmp;
}

void PrintPath()
{
	string o = "1111";
	for (int i = 15; i > 0; i = path[i])
	{
		string t = BtoS(path[i]);	//转换后:菜羊狼人 
		if(t[3] == '0' && t[0] == '0' && o[3] == '1' && o[0] == '1')
			cout << "人和菜过河" << endl;
		else
			if(t[3] == '1' && t[0] == '1' && o[3] == '0' && o[0] == '0')
				cout << "人和菜回来" << endl;
			else
				if(t[3] == '0' && t[1] == '0' && o[3] == '1' && o[1] == '1')
					cout << "人和羊过河" << endl;
				else
					if(t[3] == '1' && t[1] == '1' && o[3] == '0' && o[1] == '0')
						cout << "人和羊回来" << endl;
					else
						if(t[3] == '0' && t[2] == '0' && o[3] == '1' && o[2] == '1')
							cout << "人和狼过河" << endl;
						else
							if(t[3] == '1' && t[2] == '1' && o[3] == '0' && o[2] == '0')
								cout << "人和狼回来" << endl;
							else
								if(t[3] == '0' && o[3] == '1')
									cout << "人过河" << endl;
								else
									if(t[3] == '1' && o[3] == '0')
										cout << "人回来" << endl; 
		o = t;
	}
}

signed main()
{
	
	BFS();
	PrintPath();
	
	return 0;
} 
 

DFS

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<math.h>

#define TRUE      1
#define FALSE     0
#define OK        1
#define ERROR     0
#define OVERFLOW -1

typedef int Status;
typedef int ElemType;

Status f[17]={0};//记录状态是否被搜过 
int pre[17]; //记录每个合法状态的前一个状态 

int geti(int i,int n){
	//获取下一目标状态
	if(n>>3==0){
		return n+8+i;
	}
	else{
		return n-8-i;
	}
}

Status judge(int n){
	//判断该状态是否合法 
	if(n<0)
		return FALSE;
	if(n>>3==1){
		if(((n>>2)%2==0&&(n>>1)%2==0)||((n>>1)%2==0&&n%2==0))
			return FALSE;
		return TRUE;
	}
	else{
		if(((n>>2)%2==1&&(n>>1)%2==1)||((n>>1)%2==1&&n%2==1))
			return FALSE;
		return TRUE;
	}
}



void dfs(int n){
	//深度优先搜索正确的过河方案 
	f[n]=1;
	//PrintBit(n);
	for(int i=1,j=0;i<=8;i<<=1,j++){
		int x,y;
		if((n>>3)%2!=(n>>j)%2&&i!=8)
			continue;
			
		if(i==8)
			y=geti(0,n);
		else
			y=geti(i,n);
			
		if(judge(y)&&!f[y]){
			pre[y]=n;
			dfs(y);
		}
	}
}

void PrintChar(int x){
	if(x==0){
		printf("初始状态\n");
		return ;
	}
	if(x>>3==1&&pre[x]>>3==0)
		printf("人过河,");
	if(x>>3==0&&pre[x]>>3==1)
		printf("人回去,"); 
	if((x>>2)%2==1&&(pre[x]>>2)%2==0)
		printf("狼过河,");
	if((x>>2)%2==0&&(pre[x]>>2)%2==1)
		printf("狼回去,");  
	if((x>>1)%2==1&&(pre[x]>>1)%2==0)
		printf("羊过河,"); 
	if((x>>1)%2==0&&(pre[x]>>1)%2==1)
		printf("羊回去,"); 
	if(x%2==1&&pre[x]%2==0)
		printf("白菜过河,");
	if(x%2==0&&pre[x]%2==1)
		printf("白菜回去,");
	printf("\n");
}

void PrintBit(int n){
	//将十进制数转为四位二进制输出
	for(int i=3;i>=0;i--)
		printf("%d",(n>>i)%2);
	printf(":");
	PrintChar(n);
}

void PrintStep(int x){
	if(x==0){
		PrintBit(x);
		return ;
	}
	
	PrintStep(pre[x]);
	PrintBit(x);
}

int main()
{
	dfs(0);
	PrintStep(15);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值