【USACO TRAINING】母亲的牛奶
题目描述:
农民约翰有三个容量分别是A,B,C升的桶,A、B、C分别是三个从1到20的整数。
最初,A和B桶都是空的,而C桶是装满牛奶的。
有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。
输入:
第1行:3个整数A,B和C。
输出:
第1行:升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。
样例输入:
2 5 10
样例输出:
5 6 7 8 9 10
题目分析:
这道题是搜索的一道经典题——深度优先搜索和广度优先搜索都可以完成,这里作者为大家介绍广度优先搜索的做法。与一般的广度优先搜索不同,每一次搜索都有两个自变化的变量——从a桶倒入b桶,因此我们要用两个for循环。注意此时的a和b不能相等 否则就会出现无限循环的危险。
从a桶倒入b桶有两种情况:a桶全部倒空;b桶已经装满(有时将会出现a桶倒完,同时b桶也装满的情况,算入情况1)。若此时为情况1,则不需考虑溢出(超出最大容量),否则b桶就装满,a桶有剩余。由题目描述得:“A和B桶都是空的,而C桶是装满牛奶的”,即牛奶的总量总是c桶的初始值,因此我们可以 用c桶的初始值减去现在a,b桶的值得到现在c桶的值。
得到此时a,b,c桶的值后,需要判断是否重复,可以使用一个二维的bool数组,用类似于“桶排序”的方式储存当前a,b桶的值(c桶无需储存,可以通过a,b桶求得)。若重复,则不储存,否则列入bool数组中,并将其入队。
一直循环到所有的情况完毕,再遍历bool数组中所有的a桶为零的元素([0][b桶]),若出现过(true),则输出。注意b桶的值需要从大到小循环(保证c桶的值从小到大输出)。
程序样例:
#include<cstdio>
#include<queue> //C++特有队列
#include<algorithm>
using namespace std;
int barrel[3];bool can[25][25];
//a,b,c桶的初值 ; 判断是否重复的数组
struct BARREL{int A_barrel,B_barrel;}now; //保存a,b桶的值
queue<BARREL> que; //建立FIFO队列
int main()
{
scanf("%d%d%d",&barrel[0],&barrel[1],&barrel[2]);
now.A_barrel=now.B_barrel=0;
que.push(now); //初始化队列
while(!que.empty()) //一直循环到队列为空
{
for(int i=0;i<3;i++) //将i桶倒入j桶
for(int j=0;j<3;j++)
{
if(i==j) continue; //避免重复
int now_barrel[3]; //当前a,b,c桶
now_barrel[0]=que.front().A_barrel;
now_barrel[1]=que.front().B_barrel;
//a,b桶初始值
now_barrel[2]=barrel[2]-now_barrel[0]-now_barrel[1]; //c桶=总量(c桶初始值)-a桶-b桶
int pour=now_barrel[i]+now_barrel[j]; //i桶和j桶的总和
now_barrel[j]=min(pour,barrel[j]); //避免j桶溢出
now_barrel[i]=pour-now_barrel[j]; //求出i桶剩余
if(!can[now_barrel[0]][now_barrel[1]]) //判断重复
{
can[now_barrel[0]][now_barrel[1]]=true;
now.A_barrel=now_barrel[0];
now.B_barrel=now_barrel[1];
que.push(now); //入队
}
}
que.pop(); //更新队首
}
bool first=true;
for(int i=20;i>=0;i--) //从大到小枚举b桶
if(can[0][i]) //此情况出现过
{
first? first=false:printf(" ");
printf("%d",barrel[2]-i); //输出
}
return 0;
}
/**************************************************************
Language: C++
Result: 正确
Time:0 ms
Memory:1052 kb
***************************************************************/