ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

倒水问题

2022-07-21 10:05:18  阅读:145  来源: 互联网

标签:倒水 状态 int 问题 4000 ans 杯子


倒水问题

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

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

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

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

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

输入格式

输入包含多组测试数据。

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

输出格式

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

数据范围

$0 \leq A,B,C \leq 4000$,
每个输入最多包含 $100$ 组数据。

输入样例:

0 5 5
2 2 4

输出样例:

2
3

 

解题思路

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

  分析一下一共有多少种状态,每个杯子的容量最多是$4000$,因此三个杯子一共会有$4000^3$种不同的状态。但实际上每次倒水后必然至少有一个杯子是空的或者是满的,因此实际上的状态数为$2 \times 3 \times 4000^2$,这里的$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 }

 

参考资料

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

标签:倒水,状态,int,问题,4000,ans,杯子
来源: https://www.cnblogs.com/onlyblues/p/16500822.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有