倒水问题(搜索)

题意

有三个杯子,容量分别为\(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;
}
posted @ 2022-07-07 00:14  pbc的成长之路  阅读(43)  评论(0)    收藏  举报