• USACO Section 1.4 Mother's Milk 解题报告


    题目

    题目描述

    有三个牛奶桶,三个桶的容积分别是A,B,C,最小为1,最大为20。刚开始只有第三个桶里面装满了牛奶,其余两个桶都是空的。我们现在可以将第三个桶中的牛奶往其他两个桶里面倒一些牛奶,然后还可以将其他两个桶往另一个桶中倒牛奶,但是我们在操作的时候有严格的要求:
    从一个桶往另一个桶中倒牛奶,要么直到第二个桶已经装满了,要么直到第一个桶已经空了。在倒牛奶的过程中不允许浪费。
    在来回经过一系列的倒牛奶的操作之后,现在我们需要知道当第一个牛奶桶为空的时候,第三个牛奶桶可能的牛奶量为多少。

    输入

    一行输入三个整数 A,B,C。

    输出

    按照从小到大的顺序输出当第一个桶为空时第三个桶中的可能牛奶量。

    输入样例

    8 9 10
    

    输出样例

    1 2 8 9 10
    

    输入样例

    2 5 10
    

    输出样例

    5 6 7 8 9 10
    

    题目分析

    最开始拿到这个题目的时候想过用枚举的方法来实现,但是在如何处理状态的地方卡住了,不知道怎样才能停止。基础还是不扎实啊,思维不够。
    用暴力枚举来求解这个题目,因为每个桶的状态最多为20,那么最多的状态为20*20*20=8000,这个数据量不算大,所以我们可以用一个三维的布尔类型状态数组来记录。states[a][b][c]表示三个桶的牛奶分别为a,b,c时的状态。状态是通过倒牛奶的操作来实现的,只有6种操作来转移状态:
    A->B A->C B->A B->C C->A C->B,我们只要将这六种操作模拟出来就行了。

    代码

    /*
    ID: yinzong2
    PROG: milk3
    LANG: C++11
    */
    #define MARK
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int maxn = 21;
    
    int A,B,C;
    int states[maxn][maxn][maxn];
    
    void solve(int a, int b, int c);
    
    void next(int x, int y, int z) {
        if (!states[x][y][z]) {
            states[x][y][z] = true;
            solve(x, y, z);
        }
    }
    // 枚举所有的可能状态,如果某个状态已经到达过,那么就不需要处理它
    void solve(int a, int b, int c) {
        int x, y, z;
        // A->B
        x = 0; y = a+b; z = c;
        if (y > B) {
            x = y-B;
            y = B;
        }
        next(x, y, z);
        // A->C;
        x = 0; y = b; z = a+c;
        if (z > C) {
            x = z-C;
            z = C;
        }
        next(x, y, z);
        // B->A
        x = a+b; y = 0; z = c;
        if (x > A) {
            y = x-A;
            x = A;
        }
        next(x, y, z);
        // B->C
        x = a; y = 0; z = b+c;
        if (z > C) {
            y = z-C;
            z = C;
        }
        next(x, y, z);
        // C->A
        x = a+c; y = b; z = 0;
        if (x > A) {
            z = x-A;
            x = A;
        }
        next(x, y, z);
        // C->B
        x = a; y = b+c; z = 0;
        if (y > B) {
            z = y-B;
            y = B;
        }
        next(x, y, z);
    }
    
    int main() {
    #ifdef MARK
        freopen("milk3.in", "r", stdin);
        freopen("milk3.out", "w", stdout);
    #endif // MARK
        while (cin >> A >> B >> C) {
            memset(states, false, sizeof(states));
            states[0][0][C] = true;
            solve(0, 0, C);
            bool first = true;
            for (int c = 0; c <= C; ++c) {
                if (states[0][C-c][c]) {
                    if (!first) cout << " ";
                    cout << c;
                    first = false;
                }
            }
            cout << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    ALinq Dynamic 使用指南——前言
    前端与后端分离的架构实例(三)
    前端与后端分离的架构实例(二)
    启动画面QSplashScreen鼠标点击的时候不退出
    Qt组件屏蔽鼠标激活
    Qt LNK2001错误
    QtDesigner中设定一个组件位于另一个组件上方
    QToolButton设置图片
    osgearth_package切片工具切局部影像或者高程tif无法生成切片问题;切完数据集无法显示问题
    Qt输入框添加搜索按钮,以及自动补全内容
  • 原文地址:https://www.cnblogs.com/yinzm/p/7424214.html
Copyright © 2020-2023  润新知