题意
有三个杯子,容量分别为\(A,B,C\)。
初始时,\(C\)杯装满了水,而\(A,B\)杯都是空的。
现在在保证不会有漏水的情况下进行若干次如下操作:
将一个杯子\(x\)中的水倒到另一个杯子\(y\)中,当\(x\)空了或者\(y\)满了时就停止(满足其中一个条件才停下)。
请问,在操作全部结束后,\(C\)中的水量有多少种可能性。
题目链接:https://www.acwing.com/problem/content/3514/
数据范围
\(0 \leq A,B,C \leq 4000\)
思路
考虑用DFS爆搜,dfs(x, y, z)
表示当前搜索到的状态(三个杯子当前的水量)
下面主要分析时间复杂度。
每个状态至少会有一个杯子是空的或者满的,因此状态总数为\(O(4001 * 4001 * 2 * 3)\)
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <set>
using namespace std;
typedef pair<int, int> pii;
typedef pair<pii, int> ppi;
int v[3];
set<int> ans;
set<ppi> st;
void dfs(int x, int y, int z)
{
ans.insert(z);
st.insert({{x, y}, z});
int t[3] = {x, y, z};
for(int i = 0; i < 3; i ++) {
for(int j = 0; j < 3; j ++) {
if(i == j) continue;
int tt[3] = {x, y, z};
int mi = min(tt[i], v[j] - tt[j]);
tt[i] -= mi, tt[j] += mi;
if(!st.count({{tt[0], tt[1]}, tt[2]})) dfs(tt[0], tt[1], tt[2]);
}
}
}
int main()
{
while(~scanf("%d%d%d", &v[0], &v[1], &v[2])) {
ans.clear();
st.clear();
dfs(0, 0, v[2]);
printf("%d\n", ans.size());
}
return 0;
}