-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
- FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
- DROP(i) empty the pot i to the drain;
- POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.
输入
-
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
输出
-
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.
样例输入
-
3 5 4
样例输出
6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1)
分析:这道题目就是一道很普通的广搜题目,但是因为它里面涉及到了很多的选择,也涉及到了回溯,所以对于基本功和基本的广搜算法的联系很有意义,对于新手来说是很宝贵的锻炼机会。
思路很简单,对于每个状态用一个status的结构存储,记录下来两个水壶里的水量、现在是第几步、达到这个状态的上一步操作(我们可以用一个整数operation来存储)和这个状态的前一个状态在数组的什么位置(用来回溯)。
上代码:
#include<iostream> #include<cstring> #include<algorithm> using namespace std; struct status { int pot1; int pot2; int opration;//0,1 fill;2,3 pour;4,5 drop int steps; int signal; status(int a, int b, int c) :pot1(a), pot2(b), steps(c) {} status() {} }; status open[40000]; bool walked[110][110]; void Print(int x) { //针对对应的operation打印 if (x == 0) cout << "FILL(1)" << endl; else if (x == 1) cout << "FILL(2)" << endl; else if (x == 2) cout << "POUR(1,2)" << endl; else if (x == 3) cout << "POUR(2,1)" << endl; else if (x == 4) cout << "DROP(1)" << endl; else cout << "DROP(2)" << endl; return; } int main() { int x1, x2, y; cin >> x1 >> x2 >> y; status tmp(0, 0, 0); open[0] = tmp; status *head, *tail; head = open; tail = open + 1; head->signal = 0; walked[0][0] = true; int flag = 0; while (head != tail) { tmp = *head; if (tmp.pot1 == y || tmp.pot2 == y) { flag = 1; break; } for (int ope = 0; ope < 6; ope++) { switch (ope) { case 0: if (tmp.pot1 != x1 && !walked[x1][tmp.pot2]) { *tail = status(x1, tmp.pot2, tmp.steps + 1); walked[x1][tmp.pot2] = true; tail->opration = 0; tail->signal = head - open; tail++; } break; case 1: if (tmp.pot2 != x2 && !walked[tmp.pot1][x2]) { *tail = status(tmp.pot1, x2, tmp.steps + 1); tail->opration = 1; walked[tmp.pot1][x2] = true; tail->signal = head - open; tail++; } break; case 2: if (tmp.pot1 != 0 && tmp.pot2 < x2) { if (tmp.pot1 >= (x2 - tmp.pot2) && !walked[tmp.pot1 + tmp.pot2 - x2][x2]) { *tail = status(tmp.pot1 + tmp.pot2 - x2, x2, tmp.steps + 1); tail->opration = 2; walked[tail->pot1][tail->pot2] = true; tail->signal = head - open; tail++; } else if (tmp.pot1 + tmp.pot2 <= x2 && !walked[0][tmp.pot1 + tmp.pot2]) { *tail = status(0, tmp.pot1 + tmp.pot2, tmp.steps + 1); tail->opration = 2; walked[tail->pot1][tail->pot2] = true; tail->signal = head - open; tail++; } } break; case 3: if (tmp.pot2 != 0 && tmp.pot1 < x1) { if (tmp.pot2 >= (x1 - tmp.pot1) && !walked[x1][tmp.pot1 + tmp.pot2 - x1]) { *tail = status(x1, tmp.pot1 + tmp.pot2 - x1, tmp.steps + 1); tail->opration = 3; walked[tail->pot1][tail->pot2] = true; tail->signal = head - open; tail++; } else if (tmp.pot1 + tmp.pot2 <= x1 && !walked[tmp.pot1 + tmp.pot2][0]) { *tail = status(tmp.pot1 + tmp.pot2, 0, tmp.steps + 1); tail->opration = 3; walked[tail->pot1][tail->pot2] = true; tail->signal = head - open; tail++; } } break; case 4: if (tmp.pot1 != 0 && !walked[0][tmp.pot2]) { *tail = status(0, tmp.pot2, tmp.steps + 1); tail->opration = 4; walked[tail->pot1][tail->pot2] = true; tail->signal = head - open; tail++; } break; case 5: if (tmp.pot2 != 0 && !walked[tmp.pot1][0]) { *tail = status(tmp.pot1, 0, tmp.steps + 1); tail->opration = 5; walked[tail->pot1][tail->pot2] = true; tail->signal = head - open; tail++; } break; } } head++; } if (flag == 0) cout << "impossible" << endl; else { int t = head->steps; cout << t << endl; int *sol = new int[t]; int temp = head - open; for (int i = t - 1; i >= 0; i--) { sol[i] = open[temp].opration; if (i != 0) temp = open[temp].signal; } for (int i = 0; i < t; i++) Print(sol[i]); } return 0; }
恍恍惚惚就写了140多行,应该还有优化的空间,但是最近期末了,优化的工作就先交给读者了!