倒水问题

倒水问题

有三个杯子,容量分别为 A,B,C

初始时,C 杯装满了水,而 A,B 杯都是空的。

现在在保证不会有漏水的情况下进行若干次如下操作:

将一个杯子 x 中的水倒到另一个杯子 y 中,当 x 空了或者 y 满了时就停止(满足其中一个条件才停下)。

请问,在操作全部结束后,C 中的水量有多少种可能性。

输入格式

输入包含多组测试数据。

每组数据占一行,包含三个整数 A,B,C

输出格式

每组数据输出一个结果,占一行。

数据范围

0A,B,C4000,
每个输入最多包含 100 组数据。

输入样例:

0 5 5
2 2 4

输出样例:

2
3

 

解题思路

  一开始直接写了个爆搜,结果写了半天还写错了,一共有六种倒水的方式,如果每种情况都手写一遍很麻烦而且很容易错,这里有个更为巧妙的方法,利用循环和数组来枚举这六种情况。

  分析一下一共有多少种状态,每个杯子的容量最多是4000,因此三个杯子一共会有40003种不同的状态。但实际上每次倒水后必然至少有一个杯子是空的或者是满的,因此实际上的状态数为2×3×40002,这里的2是指空或满的情况,3是指从三个杯子中选一个是空或满的状态。当然这个是一个上限值,实际上的状态数是远远小于这个数的。

  因此需要枚举每一个状态,从一个状态转移到另外一个状态,可以看作是图的遍历。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const LL B = 1000;
 7 
 8 int a[3];
 9 unordered_set<LL> st;
10 unordered_set<int> ans;
11 
12 LL get(int *b) {    // 把三个杯子中的水(状态)映射成一个LL
13     return b[0] * B * B + b[1] * B + b[0];
14 }
15 
16 void dfs(int *b) {
17     if (st.count(get(b))) return;   // 记录状态,避免重复搜索
18     st.insert(get(b));
19     ans.insert(b[2]);
20     
21     // 枚举所有的情况,从i倒水到j
22     for (int i = 0; i < 3; i++) {
23         for (int j = 0; j < 3; j++) {
24             if (i == j) continue;   // 不可以自己倒水给自己
25             int t = min(b[i], a[j] - b[j]); // 取i杯子当前盛水量与j杯子剩余容量的最小值
26             int c[3] = {b[0], b[1], b[2]};  // 为了恢复现场开个临时数组
27             c[i] -= t, c[j] += t;   // 倒水
28             dfs(c);
29         }
30     }
31 }
32 
33 int main() {
34     while (~scanf("%d %d %d", a, a + 1, a + 2)) {
35         st.clear();
36         ans.clear();
37         int b[3] = {0, 0, a[2]};
38         dfs(b);
39         printf("%d\n", ans.size());
40     }
41     
42     return 0;
43 }
复制代码

  可以发现,dfs的代码与图的深度优先遍历是几乎一样的。17行表示如果这个结点(状态)以及访问过了就不再访问。18行表示该结点(状态)已经被访问过了。 2230行表示遍历当前结点(状态)相连的边,即与当前结点(状态)相邻的结点(状态)。因此整个状态的遍历可以看作是图的深度优先遍历。

 

参考资料

  AcWing 3511. 倒水问题(暑假每日一题2022):https://www.acwing.com/video/4064/

posted @   onlyblues  阅读(419)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2021-07-21 二分查找模板
Web Analytics
点击右上角即可分享
微信分享提示