USACO1.4.4 Mother's Mil 母亲的牛奶 题解报告(dfs)

题目描述
农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,最初,A和B桶都是空的,而C桶是装满牛奶的。有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。 写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。

Input
单独的一行包括三个整数A,B和C。

Output
只有一行,列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。

Sample Input
8 9 10
Sample Output
1 2 8 9 10

倒水总共6种状态,分别为

  • A->B
  • B->A
  • A->C
  • C->A
  • B->C
  • C->B
    记杯子i容量为vi,杯子内所含水为wi;
    所以我们记录每一次ABCw(其实只需要记录2个杯子即可,任意2个杯子w确定了那么第3个杯子的w),然后对以上6种情况进行遍历,如果碰见当前w0,w1,w2的组合未被标记,则以当前w0,w1,w2标记并以其为起点进行深搜,这样就能求出任意两个杯子相互倒水的所有情况了。然后取w0=0的时候w2的值即可
    AC代码如下
#include <map>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <iostream>
#include <algorithm>
#define fori(a) for(int i=0;i<a;i++)
#define forj(a) for(int j=0;j<a;j++)
#define ifor(a) for(int i=1;i<=a;i++)
#define jfor(a) for(int j=1;j<=a;j++)
#define IO do{\
    ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);}while(0)

#define mp(a,b) make_pair(a,b)
using namespace std;
typedef long long ll;
const int maxn =  210;

map <pair<int,int>,bool>q; //标记三个杯子中的当前容量是否已经遍历过,避免重复搜索
pair <int,int >buf;
map <int,bool>res;          
int cnt;
int ans[maxn];
int dir[6][2]= {{0,2},{0,2},{1,2},{1,0},{2,0},{2,1}};//从dir[i][0]往dir[i][1]中倒水
int v[3]; //每个杯子的容量
int w[3]; //每个杯子已经装了多少水
int push(int a,int b) {return min(w[a],v[b]-w[b]);} //a向b中倒水的量
void dfs() {
    if(w[0]==0&&!res[w[2]]) {   //如果A为0且C中的容量未被记录
        ans[cnt++] = w[2];
        res[w[2]] = true;
    }
    fori(6) {
        int val = push(dir[i][0],dir[i][1]);
        if(val) {
            //倒水操作
            int a = dir[i][0];
            int b = dir[i][1];
            w[a] -= val;
            w[b] += val;
            //*********//

            buf = mp(w[0],w[1]);
            if(!q[buf]) {         //如果这个结果未曾被遍历,则进入,继续dfs
                q[buf] = true;
                dfs();
            }
            w[a] += val;
            w[b] -= val;
        }

    }
}
int main() {
    fori(3)
    cin >> v[i];
    w[2] = v[2];
    dfs();
    sort(ans,ans+cnt);
    fori(cnt){
        if(i)
            cout <<" ";
        cout << ans[i];
    }
    cout << endl;
    return 0;
}
posted @ 2018-09-06 09:17  秃头大师  阅读(216)  评论(0编辑  收藏  举报