洛谷题目: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)

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

相关推荐
怕浪猫3 分钟前
2840亿参数只卖白菜价:DeepSeek V4 Flash 正式版上线,Agent 能力暴涨6倍
人工智能·算法
让学习成为一种生活方式9 分钟前
苄基异喹啉生物碱糖基转移酶UGT74AN1晶体--Journal of Agricultural and Food Chemistry
人工智能·算法
alphaTao12 分钟前
LeetCode 每日一题 2026/7/27-2026/8/2
python·算法·leetcode
2501_9269783344 分钟前
提示工程的实战报告(二):模型的失败模式与边界行为
人工智能·深度学习·算法
小小晓.1 小时前
C++记:函数
开发语言·c++·算法
casual~1 小时前
模逆元计算方法详解:扩展欧几里得算法与费马小定理
学习·算法·逆元
脚踏实地皮皮晨1 小时前
002002002_DepandencyObject类2
开发语言·windows·算法·c#·visual studio
冻柠檬飞冰走茶3 小时前
PTA基础编程题目集 7-27 冒泡法排序(C语言实现)
c语言·开发语言·数据结构·算法
大鱼>4 小时前
因子挖掘+回测+RL交易:量化金融完整系统
人工智能·深度学习·算法·金融
c238566 小时前
《枚举算法 “翻译官”:用 enum class 给 “游游的礼盒” 算分》
c语言·c++·算法