13.非常可乐(简单搜索 BFS)

非常可乐

题目

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是 seeyou 却不这么认为。

因为每次当 seeyou 买了可乐以后,阿牛就要求和 seeyou 一起分享这一瓶可乐,而且一定要喝的和 seeyou 一样多。

但 seeyou 的手中只有两个杯子,它们的容量分别是 \(N\) 毫升和 \(M\) 毫升。

可乐的体积为 \(S(S<101)\) 毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 $S=N+M,101>S>0,N>0,M>0
) $ 。

聪明的 \(ACMER\) 你们说他们能平分吗?

如果能请输出倒可乐的最少的次数,如果不能输出 NO

输入格式

输入包含多组测试数据。
每组数据一行,三个整数 \(S,N,M\)
当输入一行为 0 0 0 时,表示输入结束。

输出格式

每组数据输出一行结果,如果能够平分,则输出倒可乐的最少的次数,否则输出 NO。

数据范围

$ S=N+M,101>S>0,N>0,M>0$

输入样例:

7 4 3
4 1 3
0 0 0

输出样例:

NO
3

思路

\(BFS\) 最短步数模型,每次扩展搜索 \(6\) 种情况,第一次搜到即为最优解

代码

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int d[N][N][N];
int s,n,m;
struct Pos
{
	int x,y,z;
};

int bfs()
{
	memset(d,-1,sizeof d);
	queue<Pos>q;
	q.push({0,0,s});
	d[0][0][s]=0;
	
	while(q.size())
	{
		auto t=q.front();
		q.pop();
		
		//当有两个相同数的时候,得到答案
		if(t.x*2==s&&t.y*2==s||t.x*2==s&&t.z*2==s||t.y*2==s&&t.z*2==s)return d[t.x][t.y][t.z];
		
		
		//枚举六种情况
		int ab=min(t.x,m-t.y),ac=min(t.x,s-t.z);
		int ba=min(t.y,n-t.x),bc=min(t.y,s-t.z);
		int ca=min(t.z,n-t.x),cb=min(t.z,m-t.y);
		int dx[]={t.x-ab,t.x-ac,t.x+ba,t.x,t.x+ca,t.x};
		int dy[]={t.y+ab,t.y,t.y-ba,t.y-bc,t.y,t.y+cb};
		int dz[]={t.z,t.z+ac,t.z,t.z+bc,t.z-ca,t.z-cb};
		
		for(int i=0;i<6;i++)
		{
			int a=dx[i],b=dy[i],c=dz[i];
			
			if(d[a][b][c]==-1)
			{  
				d[a][b][c]=d[t.x][t.y][t.z]+1;
				q.push({a,b,c});
			}
		}
		
	}
	
	return -1;
}
int main()
{
	while(cin>>s>>n>>m,s&&n&&m)
	{
		int t=bfs();
		if(t==-1)puts("NO");
		else cout<<t<<endl;
	}
	
	return 0;
}
posted @ 2023-05-02 20:59  风雨zzm  阅读(27)  评论(0编辑  收藏  举报