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;
}
原文地址:https://www.cnblogs.com/heyour/p/12689824.html