卧槽!被struct折服了!以后就用它了!
题目概述:
这道题就是经典的倒水问题,不禁感慨一句以前需要人脑来做的东西现在直接计算机模拟就够了。
给定三个数字,前两个数字表示的是两个桶的最大容量,第三个数字表达的是目标容量。一共有三种操作,分别是清空某桶,装满某桶,还有把一个桶里面的水倒入另一个桶(如果会溢出就只能刚好倒满,剩下的水留在自己的桶里)。要求输出最少的操作步数,并且要输出操作方法。
算法思想:
因为题目要求输出的是最少操作步数,就想到了用BFS来枚举各个状态,而且其实可枚举出来的状态真的很少呀。
然后vis[][]这个数组记录的是(i,j)这个水流组合现在有没有出现过,这个其实不止起了优化的作用,而是保证程序可以终止,因为假如输入的数据是一个无法达到的数据的话,这个程序就会无限期枚举下去,所以这个数组就是必要的。
知道了这些之后,仍然要解决路径的问题,那么解决方法就是开了一个struct,比我那个pair<int,int>不知高到哪里去,因为这个结构体可以存储string,然后用string连接的操作就可以把所有操作记录下来,实乃高招。哦也许读者认为很容易就想到但是我比较弱啊对不起 Orz。
希望代码分层明显的读者可以自然写几个子函数,但是我当时觉得没什么必要就没写了。
代码部分:
#include <iostream> #include <queue> #include <map> #include <string> using namespace std; int a, b, c; int vis[117][117] = { 0 }; struct node{ int a_m, b_m; string step; node(int a_v, int b_v, string s_v) : a_m(a_v), b_m(b_v), step(s_v) {} }; int main() { int a, b, c; bool flag = false; cin >> a >> b >> c; queue<node> q; node start(0, 0, ""); node result(0, 0, ""); q.push(start); vis[0][0] = 1; while (!q.empty()) { if (flag) break; node next = q.front(); q.pop(); if (next.a_m == c || next.b_m == c){ flag = true; result = next; } if (next.a_m != 0) { node tmp = node(0, next.b_m, next.step + '1'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); // We don't need to check whether this satisfy results vis[tmp.a_m][tmp.b_m] = 1; } } if (next.b_m != 0) { node tmp = node(next.a_m, 0, next.step + '2'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } if (next.a_m != a) { node tmp = node(a, next.b_m, next.step + '3'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } if (next.b_m != b) { node tmp = node(next.a_m, b, next.step + '4'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } if (next.a_m != 0 && next.a_m+next.b_m <= b && next.b_m != b){ node tmp = node(0, next.a_m + next.b_m, next.step + '5'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } if (next.a_m !=0 && next.a_m+next.b_m > b && next.b_m != b){ node tmp = node(next.a_m+next.b_m-b, b, next.step + '5'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } if (next.b_m !=0 && next.a_m+next.b_m <= a && next.a_m != a){ node tmp = node(next.a_m + next.b_m, 0, next.step + '6'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } if (next.b_m != 0 && next.a_m + next.b_m>a && next.a_m != a){ node tmp = node(a, next.a_m+next.b_m-a, next.step + '6'); if (!vis[tmp.a_m][tmp.b_m]) { q.push(tmp); vis[tmp.a_m][tmp.b_m] = 1; } } } if (!flag) cout << "impossible" << endl; else { cout << result.step.size() << endl; for (int i = 0; i < result.step.size(); i++){ switch (result.step[i]) { case '1': cout << "DROP(1)" << endl; break; case '2': cout << "DROP(2)" << endl; break; case '3': cout << "FILL(1)" << endl; break; case '4': cout << "FILL(2)" << endl; break; case '5': cout << "POUR(1,2)" << endl; break; case '6': cout << "POUR(2,1)" << endl; break; } } } return 0; }