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;
}
本文来自博客园,作者:风雨zzm,转载请注明原文链接:https://www.cnblogs.com/zzmxj/p/17367984.html