Mother’s Milk解题报告
题目链接:http://train.usaco.org/usacoprob2?a=JfbzzkHQu8y&S=milk3
题目大意:FJ有三个牛奶桶,分别有A, B, C的容量。每个桶的容量都在1-20之间。一开始的时候A和B的桶是空着的,C中装满的牛奶。然后,他会把这些牛奶倒来倒去,在倒牛奶的过程中不会有任何的牛奶损失。一旦他开始倒牛奶,要么当前桶里的牛奶全部倒完了,要么目标桶的牛奶满了,他才会停下来。那么,他重复这个过程,最后C桶中会剩下多少牛奶(把所有的可能性列出来),并且A桶必须是空的。
解题思路:nocow不知道为啥上不去了,一开始没思路。后来看了一下这个小结的主题是搜索,于是就往搜索的方面考虑。因为一共就三个桶,因此每次操作一共只有六种可能: A-B, A-C, B-A, B-C, C-A, C-B。只需要把当前的状态记录下来,并且在每个状态下遍历下一个可能的状态,用堆栈就很容易实现。对每一个状态进行判断,如果这个状态下A桶是空着的,那么这时候C桶中的牛奶量就是一种可能。下面是代码:
#include <iostream>
#include <cstring>
#include <stack>
#include <fstream>
using namespace std;
struct bucketState
{
int A, B, C;
void copy(bucketState bs)
{
A = bs.A;
B = bs.B;
C = bs.C;
}
};
bool ans[21]; //用来记录C中可能的牛奶量
bool state[21][21][21]; //用来标记状态
stack<bucketState> bState;
int liter[3];
//把牛奶从一个桶倒进另一个桶,pos用来判断目标桶是哪个桶
void PourMilk(int &a, int &b, int pos)
{
if (a == 0 || b == liter[pos])
return;
if (b + a <= liter[pos])
{
b = a + b;
a = 0;
}
else
{
a = a - (liter[pos] - b);
b = liter[pos];
}
}
void GetAns()
{
bucketState bTop, bTmp;
while (bState.empty() == 0)
{
bTop = bState.top();
bState.pop();
//A->B
bTmp.copy(bTop);
PourMilk(bTmp.A, bTmp.B, 1);
if (state[bTmp.A][bTmp.B][bTmp.C] == 0)
{
bState.push(bTmp);
state[bTmp.A][bTmp.B][bTmp.C] = 1;
}
if (bTmp.A == 0)
ans[bTmp.C] = 1;
//A->C
bTmp.copy(bTop);
PourMilk(bTmp.A, bTmp.C, 2);
if (state[bTmp.A][bTmp.B][bTmp.C] == 0)
{
bState.push(bTmp);
state[bTmp.A][bTmp.B][bTmp.C] = 1;
}
if (bTmp.A == 0)
ans[bTmp.C] = 1;
//B->A
bTmp.copy(bTop);
PourMilk(bTmp.B, bTmp.A, 0);
if (state[bTmp.A][bTmp.B][bTmp.C] == 0)
{
bState.push(bTmp);
state[bTmp.A][bTmp.B][bTmp.C] = 1;
}
if (bTmp.A == 0)
ans[bTmp.C] = 1;
//B->C
bTmp.copy(bTop);
PourMilk(bTmp.B, bTmp.C, 2);
if (state[bTmp.A][bTmp.B][bTmp.C] == 0)
{
bState.push(bTmp);
state[bTmp.A][bTmp.B][bTmp.C] = 1;
}
if (bTmp.A == 0)
ans[bTmp.C] = 1;
//C->A
bTmp.copy(bTop);
PourMilk(bTmp.C, bTmp.A, 0);
if (state[bTmp.A][bTmp.B][bTmp.C] == 0)
{
bState.push(bTmp);
state[bTmp.A][bTmp.B][bTmp.C] = 1;
}
if (bTmp.A == 0)
ans[bTmp.C] = 1;
//C->B
bTmp.copy(bTop);
PourMilk(bTmp.C, bTmp.B, 1);
if (state[bTmp.A][bTmp.B][bTmp.C] == 0)
{
bState.push(bTmp);
state[bTmp.A][bTmp.B][bTmp.C] = 1;
}
if (bTmp.A == 0)
ans[bTmp.C] = 1;
}
}
int main()
{
ifstream fin("milk3.in");
ofstream fout("milk3.out");
while (fin >> liter[0] >> liter[1] >> liter[2])
{
memset(ans, 0, sizeof(ans));
memset(state, 0, sizeof(state));
ans[liter[2]] = 1; //初始状态肯定能得到
bucketState iniState;
iniState.A = 0;
iniState.B = 0;
iniState.C = liter[2];
bState.push(iniState);
state[0][0][liter[2]] = 1;
GetAns();
for (int i = 0; i < liter[2]; ++i)
{
if (ans[i] == 1)
fout << i << ' ';
}
fout << liter[2] << endl;
}
return 0;
}