题意介绍
用A,B两个杯子(A,B分别代表两个杯子的容量),通过向A,B倒满水,倒空或者A向B倒水,B向A倒水这几种方法,量出C
升水。
题意分析
隐式图问题,利用广度搜索可以解决该问题。首先,创建结构体status,他包含两个成员变量,x和y,分别表示两个杯子当前的盛水量。要得到C容量的水,无非通过上面提到的几个方法,所以需要实现这几个方法,起始状态为两个杯子都是空,从这个状态开始进行bfs,每一次都调用实现的所有方法,得到所有可能的结果放入队列,bfs结束的标志就是某一个杯子中出现C容量的水。在bfs过程中,需要记录每个状态是否被访问过,用到的数据结构为map,为了得到要求的输出结果,我们还需要一个数据结构来记录当前状态的上一个状态,采用map,同时创建了一个结构体,他的成员变量为一个status(之前创建的结构体)和一个string。
通过代码
#include
#include
#include
int A, B, C;
struct status {
int x, y;
status(){}
status(int theX, int theY) {
x = theX;
y = theY;
}
bool operator<(const status &b) const {
return x == b.x ? y < b.y : x < b.x;
}
status fillA() {
status c(A, y);
return c;
}
status fillB() {
status c(x, B);
return c;
}
status emptyA() {
status c(0, y);
return c;
}
status emptyB() {
status c(x, 0);
return c;
}
status AtoB() {
status c;
c.x = max(0, x + y - B);
c.y = min(x + y, B);
return c;
}
status BtoA() {
status c;
c.x = min(A, x + y);
c.y = max(0, x + y - A);
return c;
}
};
struct pa {
status s;
string str;
pa() {}
pa(status theS, string theStr) {
s = theS;
str = theStr;
}
};
map<status, bool> vis;
queue q;
map<status, pa>from;
void check(status s,status t, string str) {
if (vis[s] == 0) {
vis[s] = 1;
pa p(t, str);
from[s] = p;
q.push(s);
}
}
void print(status s) {
if (from.find(s) != from.end()) {
print(from[s].s);
cout << from[s].str << endl;
}
}
void bfs() {
status t(0, 0);
q.push(t);
vis[t] = 1;
while (!q.empty()) {
status temp = q.front();
q.pop(); if (temp.x==C||temp.y == C) {
print(temp);
return;
}
check(temp.AtoB(),temp,“pour A B”);
check(temp.BtoA(), temp, “pour B A”);
check(temp.fillA(), temp, “fill A”);
check(temp.fillB(), temp, “fill B”);
check(temp.emptyA(), temp, “empty A”);
check(temp.emptyB(), temp, “empty B”);
}
}
int main() {
while (cin >> A >> B >> C) {
vis.clear();
from.clear();
while (!q.empty()) q.pop();
bfs();
cout << “success” << endl;
}
return 0;
}
总结
要注意将解题的思路与现实中的做法联系起来,具体到每一步。还有就是使用map比使用普通的数组更加方便。
来源:CSDN
作者:乔亚非
链接:https://blog.csdn.net/weixin_44934885/article/details/104614103