zoukankan      html  css  js  c++  java
  • Problem E: 【宽搜入门】巧妙取量

    Description

    【题目描述】
      有三个容器,容量分别为 a,b,c(a> b > c ),一开始a装满油,现在问是否只靠abc三个容器量出k升油。如果能就输出“yes”,并且说明最少倒几次,否则输出“no”。例如:10升油在10升的容器中,另有两个7升和3升的空容器,要求用这三个容器倒油,使得最后在abc三个容器中有一个刚好存有5升油,问最少的倒油次数是多少?(每次倒油,A容器倒到B容器,或者A内的油倒完,或者B容器倒满。
     10 7 3
    (10 0 0)
    (3 7 0):第一次
    (3 4 3):第二次
    (6 4 0):第三次
    (6 1 3):第四次
    (9 1 0):第五次
    (9 0 1):第六次
    (2 7 1):第七次
    (2 5 3):第八次,出现5了。

    Input

    【输入格式】
      有多组测试数据。
      输入a,b,c, k四个正整数( 100 ≥ a > b > c≥1 , 1≤k< 100 )

    Output

    【输出格式】
      如果能得到k就输出两行。
      第一行“yes”,第二行为最少的次数
      否则输出“no”

    Sample Input

    10 7 3 5

    Sample Output

    yes
    8

    题目链接:

    简化代码(如果不能理解,请看后面的详细代码):

    #include <bits/stdc++.h>
    using namespace std;
    //最关键的两点:一、记录出现的状态,重复状态不入队;二、倒水的次序没有规定 
    struct Node{
        int step, xy[3]; //pre 表示前一步 
    };
    int k, xy[3], X[]={0, 0, 1, 1, 2, 2}, Y[]={1, 2, 0, 2, 0, 1};
    map<int, bool> mp;
    void move(int from, int to, Node now, queue<Node> &q){
        int pour=min(now.xy[from], xy[to]-now.xy[to]);
        if(pour <= 0) return ;
        now.xy[from] -= pour;
        now.xy[to] += pour;
        now.step += 1;
        int key = now.xy[0]*10000 + now.xy[1]*100 + now.xy[2];
        if(mp[key] == false){
            q.push(now);
            mp[key] = true;
        }
    }
    int BFS(){
        int i;
        Node now;
        now.xy[0]=xy[0], now.xy[1]=0, now.xy[2]=0, now.step=0;
        queue<Node> q;
        q.push(now);
        mp[now.xy[0]*10000] = true;
        while(!q.empty()){
            now = q.front();
            q.pop();
            if(now.xy[0]==k || now.xy[1]==k || now.xy[2]==k) return now.step;
            for(i=0; i<6; i++) move(X[i], Y[i], now, q);
        }
        return -1; //没有找到 
    }
    int main(){
        while(cin>>xy[0]>>xy[1]>>xy[2]>>k){
            mp.clear();
            int ans = BFS();
            if(ans != -1) printf("yes
    %d
    ", ans);
            else printf("no
    ");
        }
        return 0;
    }

    总结:将倒取的过程抽象了,省去了一些赘余的代码。

    详细版代码:

    #include <bits/stdc++.h>
    using namespace std;
    //最关键的两点:一、记录出现的状态,重复状态不入队;二、倒水的次序没有规定 
    struct Node{
        int a, b, c, step;
    }now, nex;
    int a, b, c, k;
    map<int, bool> mp;
    int BFS(){
        int i, t, pour;
        now.a=a, now.b=0, now.c=0, now.step=0;
        queue<Node> q;
        q.push(now);
        mp[now.a*10000] = true;
        while(!q.empty()){
            now = q.front();
            q.pop();
            if(now.a==k || now.b==k || now.c==k) return now.step;
            nex.step = now.step + 1; //首先步数加 1 
            //a往b倒 
            pour = min(now.a, b-now.b); //别写成 min(now.a, b-nex.b)了! 
            if(pour > 0){
                nex.a = now.a - pour;
                nex.b = now.b + pour;
                nex.c = now.c;
                t = nex.a*10000+nex.b*100+nex.c;
                if(mp[t]==false){
                    q.push(nex);
                    mp[t] = true;
                }
            }
            //a往c倒
            pour = min(now.a, c-now.c);
            if(pour > 0){
                nex.a = now.a - pour;
                nex.b = now.b;
                nex.c = now.c + pour;
                t = nex.a*10000+nex.b*100+nex.c;
                if(mp[t]==false){
                    q.push(nex);
                    mp[t] = true;
                }
            }
            //b往a倒 
            pour = min(now.b, a-now.a);
            if(pour > 0){
                nex.a = now.a + pour;
                nex.b = now.b - pour;
                nex.c = now.c;
                t = nex.a*10000+nex.b*100+nex.c;
                if(mp[t]==false){
                    q.push(nex);
                    mp[t] = true;
                }
            }
            //b往c倒
            pour = min(now.b, c-now.c);
            if(pour > 0){
                nex.a = now.a;
                nex.b = now.b - pour;
                nex.c = now.c + pour;
                t = nex.a*10000+nex.b*100+nex.c;
                if(mp[t]==false){
                    q.push(nex);
                    mp[t] = true;
                }
            }
            //c往a倒 
            pour = min(now.c, a-now.a);
            if(pour > 0){
                nex.a = now.a + pour;
                nex.b = now.b;
                nex.c = now.c - pour;
                t = nex.a*10000+nex.b*100+nex.c;
                if(mp[t]==false){
                    q.push(nex);
                    mp[t] = true;
                }
            }
            //c往b倒
            pour = min(now.c, b-now.b);
            if(pour > 0){
                nex.a = now.a;
                nex.b = now.b + pour;
                nex.c = now.c - pour;
                t = nex.a*10000+nex.b*100+nex.c;
                if(mp[t]==false){
                    q.push(nex);
                    mp[t] = true;
                }
            }
        }
        return -1; //没有找到 
    }
    int main(){
        while(cin>>a>>b>>c>>k){
            if(k > a){ //测试用例没有涉及到这点,其实可以忽略
                printf("no
    ");
            }else{
                int ans = -1;
                mp.clear();
                ans = BFS();
                if(ans != -1) printf("yes
    %d
    ", ans);
                else printf("no
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    POJ 3695 Rectangles
    POJ 2002 Squares
    linux 查看磁盘空间大小
    keymaster 快捷键管理器
    Pxloader
    as3数据类型检查写法(is/as/typeof/in/instanceof)用法介绍
    javascript的dom选择器
    javascript音频管理方案:SoundManager2
    Morris.js – 画折线图、面积图和环状图的统计图表库
    jsuri 让你方便的处理url
  • 原文地址:https://www.cnblogs.com/heyour/p/12689824.html
Copyright © 2011-2022 走看看