介绍:
前言:
这是一道经典的水桶分水问题,也就是 BFS广度优先搜索的模版题。这道题呢不是求某一次的 c 值,而是找出所有操作后能达到的、a 为空的局面,把每一种局面下对应的 c 桶存量收集起来,去重并升序输出。
#解题思路步骤:
1、明确问题核心:
1.1、题目中给定了 a ,b , c 三个容量的牛奶痛;每次只能见一个桶倒入另一个桶,知道源桶倒空或者装满了,牛奶的重量是不变的。要求我们找出在 a 桶为空的时候,c 桶所剩下的数值那就升序输出就可以啦。
1.2、既然在前言说明了考察的知识点,那我们直接不绕弯子了。首先,这道题在小亦的认知里适用于 BFS 的做法,就是去重遍历全部的一个状态,如果说你用其他的话比如暴力枚举,所有倒水的组合是不记录已访问的状态的,而且还会重复循环和搜索,所以呢适用于 BFS 的做法啦。
2、状态和倒水逻辑:
我们其实无法直接列举所有 c 的可能性,你得想要定义三组代表一种状态来模拟6种两年相互倒水的一个状态,然后呢在逐步判断是否都满足 a 为空的条件。
3、状态和存储:
3.1、首先 visa bc 布尔标记数组,分别记录该三元组的状态时候是否已经遍历过了。
3.2、ans集合,自动去重和升序存储所有a桶为空时c的数值。
4、BFS遍历:
整体呢使用队列来实现 BFS,小亦列举了三步:分别是初始化、状态扩展、收集结果。
4.1、初始化,从 (0,0,C)入队,标记 vis00C= ture,此时a空,直接将c=C存进答案集合。
4.2、队列循环扩渣,取出队首的桶状态,执行6种倒水操作,随后计算倒水的新桶容量,若没有访问,那就标记访问+入队🉑。
4.3、收集和输出,每取出一个状态的时候,如果当前 a 桶的存量为0,那就把当前c的数值存入集合里去,遍历有序集合,按着空哥分隔输出所有c的可能值。到此结束~
##复杂度:
1、时间复杂度:
。
2、时间复杂度:
。
###代码:
cpp
#include<bits/stdc++.h>
using namespace std;
struct State {
int a, b, c;
};
bool vis[21][21][21] = {false};
set<int> ans;
int A, B, C;
void pour(int &x_val, int &y_val, int mx, int my) {
int can = min(x_val, my - y_val);
x_val -= can;
y_val += can;
}
void bfs() {
queue<State> q;
q.push({0, 0, C});
vis[0][0][C] = true;
while (!q.empty()) {
State cur = q.front();
q.pop();
if (cur.a == 0) {
ans.insert(cur.c);
}
int a = cur.a, b = cur.b, c = cur.c;
int na = a, nb = b, nc = c;
pour(na, nb, A, B);
if (!vis[na][nb][nc]) {
vis[na][nb][nc] = true;
q.push({na, nb, nc});
}
na = a, nb = b, nc = c;
pour(na, nc, A, C);
if (!vis[na][nb][nc]) {
vis[na][nb][nc] = true;
q.push({na, nb, nc});
}
// 3. b->a
na = a, nb = b, nc = c;
pour(nb, na, B, A);
if (!vis[na][nb][nc]) {
vis[na][nb][nc] = true;
q.push({na, nb, nc});
}
// 4. b->c
na = a, nb = b, nc = c;
pour(nb, nc, B, C);
if (!vis[na][nb][nc]) {
vis[na][nb][nc] = true;
q.push({na, nb, nc});
}
// 5. c->a
na = a, nb = b, nc = c;
pour(nc, na, C, A);
if (!vis[na][nb][nc]) {
vis[na][nb][nc] = true;
q.push({na, nb, nc});
}
// 6. c->b
na = a, nb = b, nc = c;
pour(nc, nb, C, B);
if (!vis[na][nb][nc]) {
vis[na][nb][nc] = true;
q.push({na, nb, nc});
}
}
}
int main() {
cin >> A >> B >> C;
bfs();
for (auto it = ans.begin(); it != ans.end(); ++it) {
if (it != ans.begin()) cout << " ";
cout << *it;
}
cout << endl;
return 0;
}
--- 感谢观看---
制作:Code.小亦
代码提供:Code.小亦
题目思路部分提供:无
代码部分思路提供:无
知识共享:无
知识查找来源:无
初审:Code.小亦。
终审:Code.小亦。
本文章属于原创作品,禁止任何人进行转载,除合作之外!!
如在阅读中发现知识性错误、代码错误、错别字错误等情况私信博主或评论或通过邮箱2952104443@qq.com。
另:题目来源:首页 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
