分红酒
题目描述
标题:分红酒
有4个红酒瓶子,它们的容量分别是:9升, 7升, 4升, 2升
开始的状态是 [9,0,0,0],也就是说:第一个瓶子满着,其它的都空着。
允许把酒从一个瓶子倒入另一个瓶子,但只能把一个瓶子倒满或把一个瓶子倒空,不能有中间状态。
这样的一次倒酒动作称为1次操作。
假设瓶子的容量和初始状态不变,对于给定的目标状态,至少需要多少次操作才能实现?
本题就是要求你编程实现最小操作次数的计算。
输入:最终状态(逗号分隔)
输出:最小操作次数(如无法实现,则输出-1)
例如:
输入:
9,0,0,0
应该输出:
0
输入:
6,0,0,3
应该输出:
-1
输入:
7,2,0,0
应该输出:
2
对于编程题目,要求选手给出的解答完全符合ANSI C++标准,不能使用诸如绘图、Win32API、中断调用、硬件操作或与操作系统相关的API。
代码中允许使用STL类库,但不能使用MFC或ATL等非ANSI c++标准的类库。例如,不能使用CString类型(属于MFC类库)。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意选择自己使用的编译环境。
分析
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #define MAX 1500 5 6 struct ST //定义一个结构体,记录某个状态的各个酒杯的值 7 { 8 int a, b, c, d; 9 }qu[MAX]; 10 11 int visit[10][8][5]; //用于保存某个状态是否出现 12 int step[10][8][5][3]; //用于记录达到某个状态的最短路径 13 int front = -1, tail = 0; // 14 int A = 9, B = 7, C = 4, D = 2; //各个酒杯的最大值 15 int ea, eb, ec, ed; //输入的最终状态 16 17 int min(int x, int y, int z) //返回一个杯子能够向另一个杯子倒酒的量 18 { 19 if(x < z - y) 20 return x; 21 return z - y; 22 } 23 24 int EnterJudge(int x, int y, int z, int w) //判断某个状态是否出现,若出现则入队列 25 { 26 if(visit[x][y][z] == 0) 27 { 28 ++tail; 29 qu[tail].a = x; 30 qu[tail].b = y; 31 qu[tail].c = z; 32 qu[tail].d = w; 33 visit[x][y][z] = 1; 34 return 1; 35 } 36 return 0; 37 } 38 39 int bfs() //广度优先搜索 40 { 41 qu[0].a = 9; //初始状态入队列 42 qu[0].b = 0; 43 qu[0].c = 0; 44 qu[0].d = 0; 45 46 int temp, at, bt, ct, dt; 47 while(front < tail) //队列不空时循环 48 { 49 ++front; 50 if(qu[front].a == ea && qu[front].b == eb 51 &&qu[front].c == ec && qu[front].d == ed) 52 { 53 return step[ea][eb][ec][ed]; //找到要求的状态,返回最小次数 54 } 55 56 57 if(qu[front].a > 0 && qu[front].b < B) //a向b倒水 58 { 59 temp = min(qu[front].a, qu[front].b, B); 60 at = qu[front].a - temp; 61 bt = qu[front].b + temp; 62 ct = qu[front].c; 63 dt = qu[front].d; 64 if(EnterJudge(at, bt, ct, dt)) 65 step[at][bt][ct][dt] = 66 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 67 } 68 if(qu[front].a > 0 && qu[front].c < C) //a向c倒水 69 { 70 temp = min(qu[front].a, qu[front].c, C); 71 at = qu[front].a - temp; 72 bt = qu[front].b; 73 ct = qu[front].c + temp; 74 dt = qu[front].d; 75 if(EnterJudge(at, bt, ct, dt)) 76 step[at][bt][ct][dt] = 77 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 78 } 79 if(qu[front].a > 0 && qu[front].d < D) //a向d倒水 80 { 81 temp = min(qu[front].a, qu[front].d, D); 82 at = qu[front].a - temp; 83 bt = qu[front].b; 84 ct = qu[front].c; 85 dt = qu[front].d + temp; 86 if(EnterJudge(at, bt, ct, dt)) 87 step[at][bt][ct][dt] = 88 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 89 } 90 91 if(qu[front].b > 0 && qu[front].a < A) //b向a倒水 92 { 93 temp = min(qu[front].b, qu[front].a, A); 94 at = qu[front].a + temp; 95 bt = qu[front].b - temp; 96 ct = qu[front].c; 97 dt = qu[front].d; 98 if(EnterJudge(at, bt, ct, dt)) 99 step[at][bt][ct][dt] = 100 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 101 } 102 if(qu[front].b > 0 && qu[front].c < C) //b向c倒水 103 { 104 temp = min(qu[front].b, qu[front].c, C); 105 at = qu[front].a; 106 bt = qu[front].b - temp; 107 ct = qu[front].c + temp; 108 dt = qu[front].d; 109 if(EnterJudge(at, bt, ct, dt)) 110 step[at][bt][ct][dt] = 111 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 112 } 113 if(qu[front].b > 0 && qu[front].d < D) //b向d倒水 114 { 115 temp = min(qu[front].b, qu[front].d, D); 116 at = qu[front].a; 117 bt = qu[front].b - temp; 118 ct = qu[front].c; 119 dt = qu[front].d + temp; 120 if(EnterJudge(at, bt, ct, dt)) 121 step[at][bt][ct][dt] = 122 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 123 } 124 125 if(qu[front].c > 0 && qu[front].a < A) //c向a倒水 126 { 127 temp = min(qu[front].c, qu[front].a, A); 128 at = qu[front].a + temp; 129 bt = qu[front].b; 130 ct = qu[front].c - temp; 131 dt = qu[front].d; 132 if(EnterJudge(at, bt, ct, dt)) 133 step[at][bt][ct][dt] = 134 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 135 } 136 if(qu[front].c > 0 && qu[front].b < B) //c向b倒水 137 { 138 temp = min(qu[front].c, qu[front].b, B); 139 at = qu[front].a; 140 bt = qu[front].b + temp; 141 ct = qu[front].c - temp; 142 dt = qu[front].d; 143 if(EnterJudge(at, bt, ct, dt)) 144 step[at][bt][ct][dt] = 145 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 146 } 147 if(qu[front].c > 0 && qu[front].d < D) //c向d倒水 148 { 149 temp = min(qu[front].c, qu[front].d, D); 150 at = qu[front].a; 151 bt = qu[front].b; 152 ct = qu[front].c - temp; 153 dt = qu[front].d + temp; 154 if(EnterJudge(at, bt, ct, dt)) 155 step[at][bt][ct][dt] = 156 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 157 } 158 159 if(qu[front].d > 0 && qu[front].a < A) //d向a倒水 160 { 161 temp = min(qu[front].d, qu[front].a, A); 162 at = qu[front].a + temp; 163 bt = qu[front].b; 164 ct = qu[front].c; 165 dt = qu[front].d - temp; 166 if(EnterJudge(at, bt, ct, dt)) 167 step[at][bt][ct][dt] = 168 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 169 } 170 if(qu[front].d > 0 && qu[front].b < B) //d向b倒水 171 { 172 temp = min(qu[front].d, qu[front].b, B); 173 at = qu[front].a; 174 bt = qu[front].b + temp; 175 ct = qu[front].c; 176 dt = qu[front].d - temp; 177 if(EnterJudge(at, bt, ct, dt)) 178 step[at][bt][ct][dt] = 179 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 180 } 181 if(qu[front].d > 0 && qu[front].c < C) //d向c倒水 182 { 183 temp = min(qu[front].d, qu[front].c, C); 184 at = qu[front].a; 185 bt = qu[front].b; 186 ct = qu[front].c + temp; 187 dt = qu[front].d - temp; 188 if(EnterJudge(at, bt, ct, dt)) 189 step[at][bt][ct][dt] = 190 step[qu[front].a][qu[front].b][qu[front].c][qu[front].d] + 1; 191 } 192 } 193 194 return -1; 195 } 196 197 int main() 198 { 199 memset(step, 0, sizeof(step)); 200 memset(visit, 0, sizeof(visit)); 201 202 scanf("%d,%d,%d,%d", &ea, &eb, &ec, &ed); 203 204 int cnt = bfs(); 205 206 printf("%d\n", cnt); 207 208 return 0; 209 }