分析
题目给出了三个只知道容量a、b、c 但不知道刻度的空杯子,现将容量为c 的杯子倒满水,问如何移动最小量的水 量出容量d 的水。输出d和最小量,如果不能量出,则输出尽可能接近d的d’和d’的最小量。
如何倒水呢?a->b,a->c,b->a,b->c,c->a,c->b,总共六种方式。如果存储方式?这里可以考虑存储当前的杯子的水量,又因为总水量固定,所以只需要存两个杯子的水量即可。
每次倒水基于上一次的倒水状态,这里便采用队列来考虑这个问题,又因为要求的是最小水量,而不是最小次数,所以应该更进一步,采用优先队列,维护最小水量。
每次从杯子i向杯子j倒水时,杯子i是否有水?杯子j是否满了?杯子i是否能把j倒满?考虑以上问题,如果能倒则比较杯子j的剩余容量和杯子i的当前水量孰大孰小。倒的量取两者小者。于是杯子i减,杯子j加,当前倒过的水量加。
大致的思路如下:
取出当前队列的最小水量并删除,更新目的容量的最小水量(这里没有存储路径只更新结果)。再当前状态尝试六种方式,如果这种方式没有尝试过,那么入队。再取出当前队列的最小水量重复直到将所有倒法尝试过或者达到最小水量时退出。
代码
#include <cstdio>
#include <cstring>
#include <queue>
#define MAX 205
using std::priority_queue;
struct state { int v[3], d; bool operator<(state r) const { return d > r.d; } };
int v[3], d, r[MAX];
bool vis[MAX][MAX];
void bfs()
{
priority_queue<state> q;
state s;
s.v[0] = s.v[1] = 0; s.v[2] = v[2]; s.d = 0;
vis[0][0] = true;
q.push(s);
while (!q.empty()) {
s = q.top();
q.pop();
for (int i = 0; i < 3; i++)
if (r[s.v[i]] < 0 || s.d < r[s.v[i]]) r[s.v[i]] = s.d;
if (r[d] >= 0) break;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (i != j && s.v[i] && s.v[j] != v[j]) {
state u = s;
int a = (v[j] - s.v[j]) < s.v[i] ? (v[j] - s.v[j]) : s.v[i];
u.d += a; u.v[i] -= a; u.v[j] += a;
if ( !vis[u.v[0]][u.v[1]] ) {
vis[u.v[0]][u.v[1]] = true;
q.push(u);
}
}
}
}
void solve()
{
memset(vis, false, sizeof(vis)); memset(r, -1, sizeof(r));
bfs();
while (d >= 0) { if (r[d] >= 0) { printf("%d %d\n", r[d], d); return; } d--; }
}
int main()
{
int T; scanf("%d", &T);
while (T--) { scanf("%d%d%d%d", &v[0], &v[1], &v[2], &d); solve(); }
}
题目
Description
There are three jugs with a volume of a, b and c liters. (a, b, and c are positive integers not greater than 200). The first and the second jug are initially empty, while the third is completely filled with water. It is allowed to pour water from one jug into another until either the first one is empty or the second one is full. This operation can be performed zero, one or more times.
You are to write a program that computes the least total amount of water that needs to be poured; so that at least one of the jugs contains exactly d liters of water (d is a positive integer not greater than 200). If it is not possible to measure d liters this way your program should find a smaller amount of water d′ < d which is closest to d and for which d′ liters could be produced. When d′ is found, your program should compute the least total amount of poured water needed to produce d′ liters in at least one of the jugs.
Input
The first line of input contains the number of test cases. In the next T lines, T test cases follow. Each test case is given in one line of input containing four space separated integers — a, b, c and d.
Output
The output consists of two integers separated by a single space. The first integer equals the least total amount (the sum of all waters you pour from one jug to another) of poured water. The second integer equals d, if d liters of water could be produced by such transformations, or equals the closest smaller value d′ that your program has found.
Sample Input
102 2 3 4 2 96 97 199 62 11 135 70 15 15 153 184 60 184 180 180 146 167 57 83 60 181 32 50 72 85 99 132 34 13 38 109 79 26 53 14 12 143 37 165 83 73 134 189 126 29 34 91 169 23 172 67 173 127 180 181 116 168 188 79 113 175 181 4 164 76 177 11 17 102 19 190 175 125 151 130 179 171 131 161 21 121 170 80 28 151 25 150 61 169 119 13 29 9 121 77 16 40 85 98 88 45 118 80 89 31 170 46 10 12 2 78 7 195 109 148 157 103 146 133 98 138 72 42 145 7 146 192 119 132 23 31 67 97 177 141 88 170 127 124 186 135 158 105 178 127 130 67 30 121 7 53 200 14 36 78 95 91 196 159 47 77 23 19 189 100 151 176 136 78 70 55 100 166 190 28 137 70 94 97 94 22 167 100 150 178 12 4 155 128 69 184 162 116 182 92 3 122 16 133 45 124 199 62 187 159 91 166 89 190 6 161 64 169 188 172 38 137 148 199 175 162 66 193 183 107 55 48 62 144 29 70 157 196 46 5 131 12 132 113 171 88 178 137 74 85 58 166 110 102 199 182 142 38 41 65 175 46 121 96 89 74 166 149 165 101 47 188 153 151 89 179 101 1 17 67 93 151 65 74 10 8 30 64 33 170 22 71 105 108 192 142 166 22 158 158 68 25 99 6 124 54 153 188 161 42 34 169 55 52 169 98 20 43 36 199 138 13 189 58 70 45 120 181 176 40 43 56 116 198 42 118 38 138 29 194 106 182 179 39 163 51 11 148 113 170 70 46 124 34 182 59 80 133 78 80 40 172 172 97 135 98 147 14 15 147 36 152 8 104 106 191 191 41 132 116 116 195 187 2 139 54 29 170 38 138 186 83 27 171 110 159 179 134 69 34 149 153 58 81 185 187 35 164 72
Sample Output
2 2 9859 62 99 15 120 60 0 0 57 57 0 50 99 33 503 79 0 0 989 81 1850 121 0 91 0 67 127 54 0 79 0 4 0 11 1851 175 0 130 0 0 0 0 100 50 0 13 117 14 490 88 0 80 0 0 12 6 0 148 103 30 0 42 238 119 0 31 97 44 0 124 0 105 0 0 0 53 0 78 0 0 0 19 351 125 0 55 0 28 94 94 0 100 0 4 1199 158 0 0 186 43 0 62 91 75 120 60 169 3 1213 170 426 163 0 48 0 70 0 5 0 113 88 49 7196 110 102 102 0 65 46 50 0 149 1445 153 89 90 0 67 65 9 56 32 0 71 0 142 132 66 0 6 1404 161 42 42 0 0 2279 138 0 58 375 166 0 56 126 34 1480 106 0 39 695 113 0 46 0 59 78 2 0 97 0 14 252 8 0 191 0 116 0 2 705 38 0 0 0 159 0 34 0 81 140 70