//596K 32MS G++
#include <cstdio>
#include <queue>
#include <cstring>
#define MAX 102
using namespace std;
const char OP[6][10] = {
"FILL(1)", "FILL(2)",
"DROP(1)", "DROP(2)",
"POUR(1,2)", "POUR(2,1)"
};
int AMAX;
int BMAX;
int requiredV;
struct BFSNode {
int A;
int B;
int OPNum;
// 0 : fill 1, 1: fill 2, 2: DROP 1, 3: DROP 2, 4: POUR 1->2, 5
char OPArray[MAX];
};
typedef struct BFSNode BFSNode;
queue<BFSNode> BFSQueue;
char BFSFlag[MAX][MAX];
char checkAB(int A, int B, const BFSNode & curNode, int OPType) {
if (!BFSFlag[A][B]) {
int curOPNum = curNode.OPNum;
BFSFlag[A][B] = 1;
BFSNode newNode;
newNode.A = A;
newNode.B = B;
memcpy(newNode.OPArray, curNode.OPArray, sizeof(curNode.OPArray));
newNode.OPArray[curOPNum] = OPType;
newNode.OPNum = curOPNum + 1;
if (A == requiredV || B == requiredV) {
printf("%d\n", newNode.OPNum);
for (int i = 0; i < newNode.OPNum; i++) {
printf("%s\n", OP[newNode.OPArray[i]]);
}
return 1;
} else {
BFSQueue.push(newNode);
return 0;
}
}
return 0;
}
int BFS() {
while(BFSQueue.size()) {
BFSQueue.pop();
}
memset(BFSFlag, 0, sizeof(BFSFlag));
BFSNode beginNode;
beginNode.A = 0;
beginNode.B = 0;
beginNode.OPNum = 0;
memset(beginNode.OPArray, 0, sizeof(beginNode.OPArray));
BFSQueue.push(beginNode);
BFSFlag[0][0] = 1;
while(BFSQueue.size()) {
BFSNode curNode = BFSQueue.front();
BFSQueue.pop();
int curA = curNode.A;
int curB = curNode.B;
// printf("%d %d\n", curA, curB);
int curOPNum = curNode.OPNum;
// fill
if (curA < AMAX) { // A can still fill
if (checkAB(AMAX, curB, curNode, 0)) {
return 1;
}
}
if (curB < BMAX) { // B can still fill
if (checkAB(curA, BMAX, curNode, 1)) {
return 1;
}
}
// drop
if (curA > 0) { // A can drop some
if (checkAB(0, curB, curNode, 2)) {
return 1;
}
}
if (curB > 0) { // B can drop some
if (checkAB(curA, 0, curNode, 3)) {
return 1;
}
}
// pour
if (curA > 0) { // A can pour some to B
int newA;
int newB;
if (curA + curB <= BMAX) {
newA = 0;
newB = curA + curB;
} else {
newA = curA - (BMAX - curB);
newB = BMAX;
}
if (checkAB(newA, newB, curNode, 4)) {
return 1;
}
}
if (curB > 0) { // B can pour some to A
int newA;
int newB;
if (curA + curB <= AMAX) {
newB = 0;
newA = curA + curB;
} else {
newB = curB - (AMAX - curA);
newA = AMAX;
}
if (checkAB(newA, newB, curNode, 5)) {
return 1;
}
}
}
return -1;
}
void solve() {
int res = BFS();
if (res == -1) {
printf("impossible\n");
}
}
int main() {
while(scanf("%d %d %d", &AMAX, &BMAX, &requiredV) != EOF) {
if (requiredV == 0) {
printf("0\n");
} else {
solve();
}
}
}
算是经典的BFS典型题了,两个瓶子来回倒腾,最后搞出一瓶符合容量要求的水。
没啥可说的,换汤不换药,BFS即可,每次一共6种选择,根据题目给的操作的规范进行
操作,需要说的是,对某些操作,可以不用BFSFlag就将其过滤掉,比如DROP(1), 如果1本身就是空的,DROP(1)改变不了任何状态,因此不用考虑,pass.
初始时两个瓶子容量都是0。
小细节是题目最后还要求输出操作的步骤,直接在BFSNode搞一个字符串数组来保存可能超内存,
因为一共就6种操作:fill1 fill2 drop1 drop2 pour(1,2) pour(2,1) ,所以完全可以把这6种操作编号,0~5, 这样就只需要一个char数组就可以保存了,
再搞一个字符串数组S,保存上面6个操作对应的字符串, 最后输出的时候,按照编号找到S里的字符串即可.