洛谷题目:P1215 [USACO1.4] 母亲的牛奶 Mother‘s Milk 题解(本题简)

介绍:

前言:

这是一道经典的水桶分水问题,也就是 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)

特:本文章/专栏在知乎网站合规授权发布。

相关推荐
lzhdim6 小时前
AI的分类
人工智能·算法·机器学习·分类·数据挖掘
凤凰院凶涛QAQ9 小时前
《Java版数据结构 & 集合类剖析》Map & Set & 反射:“从哈希碰撞到红黑树转换,反射帮你扒开 HashMap 的桶数组看个究竟”
java·数据结构·算法
w_zero_one11 小时前
算法--模拟
java·数据结构·算法
秋天的怀念_David11 小时前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
秋天的怀念_David12 小时前
算法一千零一夜 · 第十四夜 幻方与奇妙的二进制
java·程序人生·算法
薛定e的猫咪12 小时前
(ICLR 2020)MAML 靠的不是快速学习,而是特征复用
人工智能·深度学习·学习·算法·机器学习
薛定e的猫咪12 小时前
(ICLR 2026)DF-META:面向 FJSP 的无导数元学习实例自适应调度
人工智能·深度学习·学习·算法·机器学习
小羊没烦恼!14 小时前
异步编程:线程概述及使用
java·开发语言·mysql·算法·c#
wanderist.14 小时前
202609CSP认证P3
算法
云淡风轻~窗明几净15 小时前
角谷猜想最接近严格证明的测试 Version1.1.1
人工智能·算法·机器学习·图论