先附上题目链接
一道简单的搜索题,不过有些细节还是需要注意.
方法要求最少倒水次数.和紫书上面那题的最少倒水量不同.也要简单一些.
注意题目说的是最后能否平分.是任意两个杯子平分都可以.而且都是整数,所以在奇数情况下是不可能达成的.一开始没弄懂题目说的平分的意思.白忙活了好久.还是要多读几遍题目再下手会提高效率.
题目最重要的一步就是倒水.模拟这个过程其实也很简单.枚举三个杯子为出水杯,另外两个就是入水杯.都进行倒水操作后更新一下数据再判断就可以了.理论上来说vis数组只需要两个参数就可以判断了(因为只记录两个杯子的水量第三个杯子是可以计算出来的).但题目规模偷懒用三个参数也可以.
附上代码
#include <iostream>
#include <queue>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
struct node {
int a, b, c,cost;
};
const int mn = 101;
const int INF = 0x3f3f3f3f;
bool vis[mn][mn][mn];
int cup[3];
node sta;
void dao(int& a, int& b, int ac, int bc) {
int d = bc - b;
if (a >= d) {
a -= d;
b = bc;
}
else {
b += a;
a = 0;
}
}
int curcup[3];
void bfs() {
queue<node> q;
q.push(sta);
while (!q.empty()) {
node cur = q.front();
q.pop();
if ((cur.a == 0 && cur.b == cur.c) || (cur.b==0&&cur.a==cur.c)|| (cur.c == 0 && cur.a == cur.b)) {
cout << cur.cost << endl;
return;
}
// cout << cur.a << " " << cur.b << " " << cur.c << endl;
// cout << endl;
for (int i = 0; i < 3; ++i) {
int u = 0;
for (int j = i; u<2; ++u) {
curcup[0] = cur.a;
curcup[1] = cur.b;
curcup[2] = cur.c;
j++;
if (j == 3) j = 0;
if (curcup[i] == 0) continue;
if (curcup[j] == cup[j]) continue;
dao(curcup[i],curcup[j],cup[i],cup[j]);
if (!vis[curcup[0]][curcup[1]][curcup[2]]) {
// cout << curcup[0] << " " << curcup[1] << " " << curcup[2] << endl;
vis[curcup[0]][curcup[1]][curcup[2]] = 1;
node nn = {curcup[0],curcup[1],curcup[2],cur.cost+1};
q.push(nn);
}
}
}
// cout << endl;
}
cout << "NO\n";
}
int main() {
while (cin >> cup[0] >> cup[1] >> cup[2] && cup[0]) {
memset(vis, 0, sizeof(vis));
memset(curcup, 0, sizeof(curcup));
curcup[0] = cup[0];
sta = { curcup[0],curcup[1],curcup[2],0 };
vis[curcup[0]][curcup[1]][curcup[2]] = 1;
if (cup[0] % 2 == 0) bfs();
else cout << "NO\n";
}
return 0;
}