//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里的字符串即可.