题目描述:
给你两个壶A和B,和一个整数C。有三种操作:
1.将一个壶装满。
2.将一个壶倒空。
3.将壶i的水倒入壶j中(要么壶j满了,壶i中可能还有一些水;要么壶i空了,其所有水都被移到壶j中)。
求这些操作的最短序列,使其中一个壶中的水正好为C。输出的第一行必须包含操作序列的长度K,下面的K行必须分别描述一个操作。
思路:
显然是BFS+路径回溯
六种操作:
1.将A壶装满。
2.将B壶装满。
3.将A壶倒空。
4.将B壶倒空。
5.将A壶中的水倒入B壶中。
6.将B壶中的水倒入A壶中。
拿BFS跑这六种操作,顺便记录下路径,再DFS出路径即可。
Code:
struct node {
int x, y, op;
};
struct pt{
int x, y, op, step;
} path[105][105];
char str[][10] = {
"FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(2,1)", "POUR(1,2)"};
int A, B, C;
int v[105][105];
void dfs(int x, int y) {
// 输出路径
int a = path[x][y].x;
int b = path[x][y].y;
if (path[x][y].step == 0) {
if (a == A)
cout << str[0] << endl;
if (b == B)
cout << str[1] << endl;
return;
}
dfs(a, b);
cout << str[path[x][y].op]<< endl;
}
void bfs(int v1, int v2, int L) {
m(v, 0);
for (int i = 0; i < 105; i++)
for (int j = 0; j < 105; j++)
path[i][j].op = 0, path[i][j].step = 0, path[i][j].x = 0, path[i][j].y = 0;
queue <node> q;
node start = {
0, 0, 0};
v[0][0] = 1;
q.push(start);
while (!q.empty()) {
node tep = q.front();
q.pop();
int temp;
if (tep.x == L || tep.y == L) {
cout << path[tep.x][tep.y].step << endl;
dfs(tep.x, tep.y);
return ;
}
for (int i = 0; i < 6; i++) {
//遍历六种情况
if (i == 0) {
start.x = v1;
start.y = tep.y;
} else if (i == 2) {
start.x = 0;
start.y = tep.y;
} else if (i == 1) {
start.x = tep.x;
start.y = v2;
} else if (i == 3) {
start.x = tep.x;
start.y = 0;
} else if (i == 5) {
temp = tep.x + tep.y - v2;
if (temp > 0) {
start.x = temp;
start.y = v2;
} else {
start.x = 0;
start.y = tep.x + tep.y;
}
} else if (i = 4) {
temp = tep.x + tep.y - v1;
if (temp > 0) {
start.y = temp;
start.x = v1;
} else {
start.y = 0;
start.x = tep.x + tep.y;
}
}
if (!v[start.x][start.y]) {
//入队,记录路径
path[start.x][start.y].x = tep.x;
path[start.x][start.y].y = tep.y;
path[start.x][start.y].op = i;
path[start.x][start.y].step = path[tep.x][tep.y].step + 1;
v[start.x][start.y] = 1;
q.push(start);
}
}
}
cout << "impossible" << endl;
}
int main() {
while (cin >> A >> B >> C) {
bfs(A, B, C);
}
return 0;
}