【王道】倒可乐、广度优先算法

【题意】可乐体积s=n+m,n和m是另外两个杯子的体积,只能用可乐瓶和这两个杯子来回倾倒,而且上面没有刻度。问至少需要倒几次才能实现可乐的平分,如果不能实现,输出"NO".输入为0 0 0时结束。

【广度优先搜索总结】

1.状态。我们要确定求解问题中的状态

2.状态扩展方式

3.有效状态

4.队列

5.标记

6.有效状态数

7.最优

【输入输出】

7 4 3

NO

4 1 3

【注意】1.队列实现,注意每次队列要清空   2.Q.front( )    3.如果s的体积是奇数,则不可能实现平分(因为瓶子的体积都是整数)

【代码】

#include<iostream>
#include<cstring>
#include<vector>
#include<math.h>
#include<algorithm>
#include<queue>
using namespace std;
#define maxi 0x3f3f3f3f
struct state
{
	int v1,v2,v3,t;
	
};
queue<state> Q;
int mark[102][102][102];
void atob(int &a,int va,int &b,int vb)
{
	if(a+b<=vb)
	{
		b=a+b;
		a=0;
	}
	else
	{
		a=a-(vb-b);
		b=vb;
	}
}
int main(int argc, char const *argv[])
{
	int s,n,m;
	bool flag=true;
	while(cin>>s)
	{
		cin>>n>>m;
		if(s==n&&n==m&&n==0)break;
		memset(mark,false,sizeof(mark));
		int right=s/2;
		if(right%2==1)
		{
			cout<<"NO"<<endl;
			continue;
		}
		state p;
		p.v1=s;
		p.v2=0;
		p.v3=0;
		p.t=0;
		mark[s][0][0]=true;
		Q.push(p);
		while(!Q.empty())
		{
			state now=Q.front();
			Q.pop();
			int v1,v2,v3;
			v1=now.v1;
			v2=now.v2;
			v3=now.v3;
			atob(v1,s,v2,n);
			if(mark[v1][v2][v3]==false)
			{
				if(v1==right&&v2==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v2==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v1==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				state temp;
				temp.v1=v1;
				temp.v2=v2;
				temp.v3=v3;
				temp.t=now.t+1;
				Q.push(temp);
				mark[v1][v2][v3]=true ;
			}
			v1=now.v1;
			v2=now.v2;
			v3=now.v3;
			atob(v2,n,v1,s);
			if(mark[v1][v2][v3]==false)
			{
				if(v1==right&&v2==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v2==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v1==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				state temp;
				temp.v1=v1;
				temp.v2=v2;
				temp.v3=v3;
				temp.t=now.t+1;
				Q.push(temp);
				mark[v1][v2][v3]=true ;
			}
			v1=now.v1;
			v2=now.v2;
			v3=now.v3;
			atob(v2,n,v3,m);
			if(mark[v1][v2][v3]==false)
			{
				if(v1==right&&v2==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v2==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v1==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				state temp;
				temp.v1=v1;
				temp.v2=v2;
				temp.v3=v3;
				temp.t=now.t+1;
				Q.push(temp);
				mark[v1][v2][v3]=true ;
			}
			v1=now.v1;
			v2=now.v2;
			v3=now.v3;
			atob(v3,m,v2,n);
			if(mark[v1][v2][v3]==false)
			{
				if(v1==right&&v2==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v2==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v1==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				state temp;
				temp.v1=v1;
				temp.v2=v2;
				temp.v3=v3;
				temp.t=now.t+1;
				Q.push(temp);
				mark[v1][v2][v3]=true ;
			}
			v1=now.v1;
			v2=now.v2;
			v3=now.v3;
			atob(v1,s,v3,m);
			if(mark[v1][v2][v3]==false)
			{
				if(v1==right&&v2==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v2==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v1==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				state temp;
				temp.v1=v1;
				temp.v2=v2;
				temp.v3=v3;
				temp.t=now.t+1;
				Q.push(temp);
				mark[v1][v2][v3]=true ;
			}
			v1=now.v1;
			v2=now.v2;
			v3=now.v3;
			atob(v3,m,v1,s);
			if(mark[v1][v2][v3]==false)
			{
				if(v1==right&&v2==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v2==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				if(v1==right&&v3==right)//别忘了判断有三组
				{
					cout<<now.t+1<<endl;
					flag=false;
					break;
				}
				state temp;
				temp.v1=v1;
				temp.v2=v2;
				temp.v3=v3;
				temp.t=now.t+1;
				Q.push(temp);
				mark[v1][v2][v3]=true ;
			}
		}
		if(flag)cout<<"NO"<<endl;
		while(!Q.empty())Q.pop();
	}

	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值