zoukankan      html  css  js  c++  java
  • UVA10603 Fill

    优秀的程序员一定是CV大师。能CV则CV的做法,可以省去许多编码和测试的时间。但是,如果出现小错误的话,找起来一样的费时

    问题链接UVA10603 Fill

    题意简述:有三个壶,容量分别是a、b和c升,开始时候第1个和第2个壶是空的,第3个壶是满水的。可以把一个壶的水倒入另一个壶中,直到倒空或将另外一个壶倒满。输入a、b、c和d,计算最少的倒水量,使得其中一个壶里有d升水。如果不能倒出d升水的话,那么找一个最大的d'<d。输出倒水量和d,如果找不到的话输出倒水量和d'。

    问题分析将<a,b,c>看成是状态,进行状态展开搜索。开始的时候,所有水在c中,2个a和b都空着。过程中,可以将任何1个中的水倒到另外某个中,或将目标倒满,或将源倒空。因为没有刻度,只能这样。这个过程中,如果出现某个的水量等于d就找到解了。同时,也要考虑得不到d的情况,所以过程中需要将最大的d'<d记录下来。容器间水倒来倒去,每次有6种倒法,对这6种倒法进行试探即可。求的是倒水量最小,所以用分支限界法实现,倒水量最小的状态优先展开

    程序说明搜索过的状态就不需要再搜索了,用数组notvist[][][]来标记搜索过的状态。

    这个问题的程序是先CV来的,然后做了适当的修改。参见:HDU1495非常可乐,也是一个倒水问题,只不过输入、输出以及限制条件不一样。

    AC的C++语言程序如下:

    /* UVA10603 Fill */
    
    #include <iostream>
    #include <queue>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    const int MAXN = 200;
    
    int a, b, c, d, maxd1, minamount;
    bool notvist[MAXN+1][MAXN+1][MAXN+1];
    
    struct node {
        int a, b, c, amount;
        bool operator < (const node& n) const {
            return amount > n.amount;
        }
    };
    
    int bfs()
    {
        maxd1 = 0;
        minamount = 0;
    
        priority_queue<node> q;
    
        memset(notvist, true, sizeof(notvist));
    
        node f, v;
        f.c = c;
        f.a = 0;
        f.b = 0;
        f.amount=0;
        q.push(f);
    
        notvist[f.c][f.a][f.b] = false;
    
        while(!q.empty()) {
            f = q.top();
            q.pop();
    
            if(f.a == d || f.b == d || f.c == d)
                return f.amount;
    
            if(f.a < d && f.a > maxd1) {
                maxd1 = f.a;
                minamount = f.amount;
            }
            if(f.b < d && f.b > maxd1) {
                maxd1 = f.b;
                minamount = f.amount;
            }
            if(f.c < d && f.c > maxd1) {
                maxd1 = f.c;
                minamount = f.amount;
            }
    
            // c --> a
            if(f.c && a - f.a > 0) {
                if(f.c > a - f.a) {         // c > a的剩余容量
                    v.c = f.c - (a - f.a);
                    v.a = a;
                    v.b = f.b;
                    v.amount = f.amount + (a - f.a);
                } else {                    // c <= a的剩余容量
                    v.c = 0;
                    v.a = f.a + f.c;
                    v.b = f.b;
                    v.amount = f.amount + f.c;
                }
                if(notvist[v.c][v.a][v.b]) {
                    notvist[v.c][v.a][v.b] = false;
                    q.push(v);
                }
            }
            // c --> b
            if(f.c && b - f.b > 0) {
                if(f.c > b - f.b) {         // c > b的剩余容量
                    v.c = f.c - (b - f.b);
                    v.a = f.a;
                    v.b = b;
                    v.amount = f.amount + (b - f.b);
                } else {                    // c <= b的剩余容量
                    v.c = 0;
                    v.a = f.a;
                    v.b = f.b + f.c;
                    v.amount = f.amount + f.c;
                }
                if(notvist[v.c][v.a][v.b]) {
                    notvist[v.c][v.a][v.b] = false;
                    q.push(v);
                }
            }
            // a --> c
            if(f.a && c - f.c > 0) {
                if(f.a > c - f.c) {         // a > c的剩余容量
                    v.c = c;
                    v.a = f.a - (c - f.c);
                    v.b = f.b;
                    v.amount = f.amount + (c - f.c);
                } else {                    // a <= c的剩余容量
                    v.c = f.c + f.a;
                    v.a = 0;
                    v.b = f.b;
                    v.amount = f.amount + f.a;
                }
                if(notvist[v.c][v.a][v.b]) {
                    notvist[v.c][v.a][v.b] = false;
                    q.push(v);
                }
            }
            // a --> b
            if(f.a && b - f.b > 0) {
                if(f.a > b - f.b) {         // a > b的剩余容量
                    v.c = f.c;
                    v.a = f.a - (b - f.b);
                    v.b = b;
                    v.amount = f.amount + (b - f.b);
                } else {                    // a <= b的剩余容量
                    v.c = f.c;
                    v.a = 0;
                    v.b = f.b + f.a;
                    v.amount = f.amount + f.a;
                }
                if(notvist[v.c][v.a][v.b]) {
                    notvist[v.c][v.a][v.b] = false;
                    q.push(v);
                }
            }
            // b --> c
            if(f.b && c - f.c > 0) {
                if(f.b > c - f.c) {         // b > c的剩余容量
                    v.c = c;
                    v.a = f.a;
                    v.b = f.b - (c - f.c);
                    v.amount = f.amount + (c - f.c);
                } else {                    // b <= c的剩余容量
                    v.c = f.c + f.b;
                    v.a = f.a;
                    v.b = 0;
                    v.amount = f.amount + f.b;
                }
                if(notvist[v.c][v.a][v.b]) {
                    notvist[v.c][v.a][v.b] = false;
                    q.push(v);
                }
            }
            // b --> a
            if(f.b && a - f.a > 0) {
                if(f.b > a - f.a) {         // b > a的剩余容量
                    v.c = f.c;
                    v.a = a;
                    v.b = f.b - (a - f.a);
                    v.amount = f.amount + (a - f.a);
                } else {                    // b <= a的剩余容量
                    v.c = f.c;
                    v.a = f.a + f.b;
                    v.b = 0;
                    v.amount = f.amount + f.b;
                }
                if(notvist[v.c][v.a][v.b]) {
                    notvist[v.c][v.a][v.b] = false;
                    q.push(v);
                }
            }
        }
    
        return -1;
    }
    
    int main()
    {
        int t;
    
        scanf("%d", &t);
        while(t--) {
            scanf("%d%d%d%d", &a, &b, &c, &d);
    
            int ans = bfs();
    
            if(ans < 0) {
                printf("%d %d
    ", minamount, maxd1);
            } else
                printf("%d %d
    ", ans, d);
        }
    
        return 0;
    }


  • 相关阅读:
    移动端按钮居底
    easyui用KindEditor编辑器
    查找数组中与后面项匹配的和猴子选大王
    before和after的样式符号
    jq的select
    验证最多2位小数,1到10 不超过10 带两位小数的正则表达式
    在谷歌浏览器下vue的@input事件问题
    mvc项目+vue+vant【进行中】
    微商代理查询系统 开发完成,免费体验试用哦!
    淘宝出了个麻吉宝区块连产品,附带麻吉宝邀请码!
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7564358.html
Copyright © 2011-2022 走看看