分酒问题(BFS或DFS)

99 篇文章 0 订阅
63 篇文章 0 订阅

      

      已知有三个容量分别为1斤、7两和3两的并且是没有刻度的酒瓶,1斤的瓶子装满了酒,而7两和三两的瓶子为空。现要求将这些酒分出5两出来。


BFS:

#include<iostream>  
#include<stdio.h>  
#include<map>  
#include<vector>  
#include<queue>  
#include<set>  
#include<cstdlib>  
#include<string.h>  
#include<algorithm>  
#include<cmath>  
#define MAXN 1000010  
#define EPS 1e-9  

using namespace std;

struct node{
	int a;//对应容量为一斤的瓶子里当前所装的酒量 
	int b;//对应容量为七两的瓶子里当前所装的酒量 
	int c;//对应容量为三两的瓶子里当前所装的酒量 
	int pre;//父节点id 
	int id;//节点id 
	string str;//记录该状态对应的操作 
}state[1000010];

int vis[100][100][100];
int cnt;
int num;
int ids[1000];

/**************************************** 
BFS函数说明:枚举各种倒满方案,依次进行广搜
参数:v1,v2,v3依次为瓶子容量,a,b,c为所装酒量,x为要称出的酒量    
********************************************/   
int BFS(int v1,int v2,int v3,int a,int b,int c,int x)
{
	int fg=-1; 
	num=0;
	queue<node>q;
	memset(vis,0,sizeof(vis));
	node cur,nex;
	cur.a=a;
	cur.b=b;
	cur.c=c;
	cur.str="";
	cur.pre=cur.id=0;
	q.push(cur);
	vis[a][b][c]=1;
	cnt=0;
	state[cnt]=cur;
	while(!q.empty())
	{
		cur=q.front();
		q.pop();
		if(cur.a==x||cur.b==x||cur.c==x)//找到解 
		{
			fg=1;
			ids[++num]=cur.id;
			continue;
			//return cur.id;
		}
		else
		{
			//1斤倒满7两
			if(cur.a!=0 && cur.b!=v2)
			{
				nex.str="a->b ";
				if(cur.a+cur.b <= v2)
				{
					nex.a=0;
					nex.b=cur.b+cur.a;
					nex.c=cur.c;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
				else
				{
					nex.a=cur.b+cur.a-v2;
					nex.b=v2;
					nex.c=cur.c;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
			}
			//7两倒满1斤
			if(cur.a!=v1 && cur.b!=0)
			{
				nex.str="b->a ";
				if(cur.a+cur.b <= v1)
				{
					nex.b=0;
					nex.a=cur.b+cur.a;
					nex.c=cur.c;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
				else
				{
					nex.b=cur.b+cur.a-v1;
					nex.a=v1;
					nex.c=cur.c;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}	
			}
			//1斤倒满3两
			if(cur.a!=0 && cur.c!=v3)
			{
				nex.str="a->c ";
				if(cur.a+cur.c <= v3)
				{
					nex.a=0;
					nex.c=cur.c+cur.a;
					nex.b=cur.b;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
				else
				{
					nex.a=cur.c+cur.a-v3;
					nex.c=v3;
					nex.b=cur.b;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
			}
			//3两倒满1斤
			if(cur.a!=v1 && cur.c!=0)
			{
				nex.str="c->a ";
				if(cur.a+cur.c <= v1)
				{
					nex.c=0;
					nex.a=cur.c+cur.a;
					nex.b=cur.b;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
				else
				{
					nex.c=cur.c+cur.a-v1;
					nex.a=v1;
					nex.b=cur.b;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
			}
			//7两倒满3两
			if(cur.b!=0 && cur.c!=v3)
			{
				nex.str="b->c ";
				if(cur.b+cur.c <= v3)
				{
					nex.b=0;
					nex.c=cur.c+cur.b;
					nex.a=cur.a;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
				else
				{
					nex.b=cur.c+cur.b-v3;
					nex.c=v3;
					nex.a=cur.a;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
			}
			//3两倒满7两
			if(cur.c!=0 && cur.b!=v2)
			{
				nex.str="c->b ";
				if(cur.b+cur.c <= v2)
				{
					nex.c=0;
					nex.b=cur.c+cur.b;
					nex.a=cur.a;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
				else
				{
					nex.c=cur.c+cur.b-v2;
					nex.b=v2;
					nex.a=cur.a;
					if(!vis[nex.a][nex.b][nex.c])
					{
						nex.pre=cur.id;
						cnt++;
						nex.id=cnt;
						state[cnt]=nex;
						q.push(nex);
						vis[nex.a][nex.b][nex.c]=1; 
					}
				}
			}
		}
	}
	return fg;//无解 
}

int path[1000000];
void track(int id)//倒推得到分酒步骤 
{
	
	int num=0;
	int i=id;
	int j;
	path[++num]=i;
	while(state[i].pre!=i)
	{
		i=state[i].pre;
		path[++num]=i;
	}
	for(j=num;j>=1;j--)
	{
		cout<<state[path[j]].str ;
	}
	puts("");
}

int main() 
{	
	int a,b;
	int t=BFS(10,7,3,10,0,0,5);
//	printf("%d\n",t);
    if(t!=-1)
    {
    	for(int i=1;i<=num;i++)
    	{
    		printf("第%d种分酒方案如下:\n",i); 
			track(ids[i]);
		}
	}
	else
	{
		printf("无解\n"); 
	}    
	return 0;
}



DFS:

#include<iostream>  
#include<stdio.h>  
#include<map>  
#include<vector>  
#include<queue>  
#include<set>  
#include<cstdlib>  
#include<string.h>  
#include<algorithm>  
#include<cmath>  

using namespace std;

int vis[100][100][100];

char path[100000][2];

int cnt=0;

void dfs(int a,int b,int c,int step)
{
	if(a<0 || b<0 || c<0 || a>10 || b>7 || c>3 || vis[a][b][c])
		return;
	vis[a][b][c]=1;
	if(a==5 || b==5 || c==5)
	{
		cnt++;
		printf("第%d种分酒方案如下:\n",cnt);
		for(int i=1;i<step;i++)
		{
			printf("%c->%c ",path[i][0],path[i][1]);
		}
		puts("");
		vis[a][b][c]=0;
		return;
	}
	else
	{
		//1斤倒满7两
		path[step][0]='a';
		path[step][1]='b';
		dfs(0,a+b,c,step+1);	
		dfs(a+b-7,7,c,step+1);
		
		//7两倒满1斤
		path[step][0]='b';
		path[step][1]='a';
		dfs(a+b,0,c,step+1);
		dfs(10,a+b-10,c,step+1);
		
		//1斤倒满3两
		path[step][0]='a';
		path[step][1]='c';
		dfs(0,b,a+c,step+1);
		dfs(a+c-3,b,3,step+1);
		
		//3两倒满1斤
		path[step][0]='c';
		path[step][1]='a';
		dfs(a+c,b,0,step+1);
		dfs(10,b,a+c-10,step+1);
		
		
		//7两倒满3两
		path[step][0]='b';
		path[step][1]='c';
		dfs(a,0,b+c,step+1);
		dfs(a,b+c-3,3,step+1);
		
		//3两倒满7两
		path[step][0]='c';
		path[step][1]='b';
		dfs(a,b+c,0,step+1);
		dfs(a,7,b+c-7,step+1);
	}
} 

int main() 
{	
	memset(vis,0,sizeof(vis)); 
	dfs(10,0,0,1);  
	return 0;
}



  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林下的码路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值