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

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

相关推荐
爱敲代码的小黄10 分钟前
机器学习入门:从数据、训练到业务决策
算法
数据知道11 分钟前
哈希与密码存储——bcrypt、Argon2、盐值与彩虹表
网络·算法·安全·网络安全·密码学·哈希算法
haon112221 分钟前
树模型在信贷风控怎么用——从决策树到 XGBoost
大数据·人工智能·算法·决策树·机器学习·数据挖掘
wordbaby23 分钟前
BM25 是什么?手把手拆解搜索引擎的核心算法
人工智能·算法
阳明山水33 分钟前
从相关到因果:预测科学的因果转向与可识别性挑战
人工智能·深度学习·算法·机器学习·架构
TDengine (老段)36 分钟前
TDgpt 使用 — 部署、SQL、算法
大数据·数据库·sql·算法·时序数据库·tdengine·涛思数据
不会就选b44 分钟前
数据结构之树&&二叉树(四)
数据结构·算法
hansang_IR1 小时前
【题解】P4456 [CQOI2018] 交错序列(矩阵乘法)
c++·线性代数·算法