题目链接:点我啊╭(╯^╰)╮
题目大意:
两个水壶,最大容积分别为
a
a
a 和
b
b
b,一开始为空,有三个操作:
F
I
L
L
(
i
)
FILL(i)
FILL(i) 把
i
i
i 装满
D
R
O
P
(
i
)
DROP(i)
DROP(i) 把
i
i
i 倒空
P
O
U
R
(
i
,
j
)
POUR(i,j)
POUR(i,j) 把
i
i
i 的水倒入
j
j
j,若
i
i
i 倒满
j
j
j 还有剩余,仍留在
i
i
i 内
问,怎样用最少的操作使其中至少一个水壶达到
c
c
c???
解题思路:
六入口BFS,同时记录路径,最后输出。
代码思路:
可能需要注意的就是路径记录的问题,这里用数组来记录前一个节点(其实我在这里调了半天。。。)
核心:多入口BFS+路径记录
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a, b, c, ans, cnt = 1;
bool vis[505][505];
stack <int> r;
struct pot {
int u, v;
int step;
int flag;
int pre;
};
void BFS(int u, int v) {
queue <pot> Q;
pot q, n, n_cnt[10005];
q.u = u, q.v = v;
q.step = 0; q.flag = 0;
q.pre = 0; Q.push(q);
vis[u][v] = true;
while(!Q.empty()) {
n = Q.front(); Q.pop();
for(int i=1; i<=6; i++) {
if(i==1) { //FILL u;
q.u = a;
q.v = n.v;
q.flag = 1;
}
if(i==2) { //FILL v;
q.u = n.u;
q.v = b;
q.flag = 2;
}
if(i==3) { //DROP u;
q.u = 0;
q.v = n.v;
q.flag = 3;
}
if(i==4) { //DROP v;
q.u = n.u;
q.v = 0;
q.flag = 4;
}
if(i==5) { //POUR u->v;
if(n.u>(b-n.v)) {
q.u = n.u - (b - n.v);
q.v = b;
} else {
q.u = 0;
q.v = n.u + n.v;
}
q.flag = 5;
}
if(i==6) { //POUR v->u;
if(n.v>(a-n.u)) {
q.v = n.v - (a - n.u);
q.u = a;
} else {
q.v = 0;
q.u = n.u + n.v;
}
q.flag = 6;
}
if(vis[q.u][q.v]) continue;
vis[q.u][q.v] = true;
q.step = n.step + 1;
n_cnt[cnt] = n;
q.pre = cnt++; //这里一开始弄错了、没连起来....
if(q.u==c || q.v==c) {
ans = q.step;
while(q.pre) {
r.push(q.flag);
q = n_cnt[q.pre];
}
return;
}
Q.push(q);
}
}
}
void print(){
while(!r.empty()){
int i = r.top(); r.pop();
switch(i) {
case 1:printf("FILL(1)\n");break;
case 2:printf("FILL(2)\n");break;
case 3:printf("DROP(1)\n");break;
case 4:printf("DROP(2)\n");break;
case 5:printf("POUR(1,2)\n");break;
case 6:printf("POUR(2,1)\n");break;
}
}
}
int main() {
scanf("%d%d%d", &a, &b, &c);
BFS(0, 0);
if(!ans) printf("impossible\n");
else {
printf("%d\n", ans);
print();
}
}