倒水游戏,两个水壶互相倒水,直到某个水壶中的水量到达目标值,若不能到达,输出impossible
这个题完全自己做出来还是感觉很开心的,因为以前在一次比赛上做过,但是没做出来,现在做出来说明还是成长了
广搜,以及路径记录,最后递归输出路径。
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
#define M 105
struct Path
{
int c1, c2;
} pre[M][M];
int v[3], tar, ans;
int d[M][M];
queue <int> q1, q2;
void Fill(int i, int j, const int cur[], int t[])
{
t[i] = v[i];
t[j] = cur[j];
}
void Drop(int i, int j, const int cur[], int t[])
{
t[i] = 0;
t[j] = cur[j];
}
void Pour(int i, int j, const int cur[], int t[])
{
if (cur[i] > v[j] - cur[j]) {
t[j] = v[j];
t[i] = cur[i] - v[j] + cur[j];
}
else {
t[i] = 0;
t[j] = cur[j] + cur[i];
}
}
void Do(int cur[], int t[])
{
if (!d[t[1]][t[2]]) {
d[t[1]][t[2]] = d[cur[1]][cur[2]] + 1;
pre[t[1]][t[2]].c1 = cur[1];
pre[t[1]][t[2]].c2 = cur[2];
q1.push(t[1]);
q2.push(t[2]);
}
}
bool BFS(int &c1, int &c2)
{
memset (d, 0, sizeof (d));
q1.push(0);
q2.push(0);
while (!q1.empty()) {
int cur[3];
cur[1] = q1.front();
cur[2] = q2.front();
q1.pop();
q2.pop();
//cout << cur[1] << " " << cur[2] << " " << d[cur[1]][cur[2]] << endl;
if (cur[1] == tar || cur[2] == tar) {
c1 = cur[1]; c2 = cur[2];
ans = d[cur[1]][cur[2]];
return true;
}
int t[3];
Fill(1, 2, cur, t);
Do(cur, t);
Fill(2, 1, cur, t);
Do(cur, t);
if (cur[1] == 0 && cur[2] == 0) continue;
Drop(1, 2, cur, t);
Do(cur, t);
Drop(2, 1, cur, t);
Do(cur, t);
Pour(1, 2, cur, t);
Do(cur, t);
Pour(2, 1, cur, t);
Do(cur, t);
}
return false;
}
void output(int c1, int c2)
{
if (c1 == 0 && c2 == 0) return;
int t1 = pre[c1][c2].c1;
int t2 = pre[c1][c2].c2;
output(t1, t2);
if (c1 == v[1] && c2 == t2)
printf ("FILL(1)\n");
else if (c2 == v[2] && c1 == t1)
printf ("FILL(2)\n");
else if (c1 == 0 && c2 == t2)
printf ("DROP(1)\n");
else if (c2 == 0 && c1 == t1)
printf ("DROP(2)\n");
else if (t1 > c1 && t2 < c2)
printf ("POUR(1,2)\n");
else printf ("POUR(2,1)\n");
}
int main()
{
scanf ("%d%d%d", &v[1], &v[2], &tar);
int c1, c2;
if (BFS(c1, c2)) {
printf ("%d\n", ans);
output(c1, c2);
}
else printf ("impossible\n");
return 0;
}