您的位置:首页 > 其它

USACO-Section1.4 Mother's Milk

2017-07-16 16:33 447 查看

2017-07-16

题目大意:

农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数, 最初,A和B桶都是空的,而C桶是装满牛奶的。有时,农民把牛奶从一个桶倒到 另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约, 牛奶不会有丢失

写一个程序去帮助农民找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。

样例输入:

8 9 10

样例输出:

1 2 8 9 10

题解:

这一题是我第一次使用一个三维数组来标记状态,因为有A,B,C三个桶,所以是三维。使用深度优先搜索来实现,三个瓶子中不空的瓶子轮流往另外两个瓶子中倒入,又分为两种情况,第一是瓶子中已有的牛奶可以到满整个瓶子,第二种的瓶子中已有的牛奶倒不满瓶子。然后模拟倒牛奶的过程,结束一层递归后应该进行回溯,回溯到上一层的状态。递归终点是当A是空,C里面的牛奶没有记录过,就将C里面的牛奶值插入到Set集合中。

代码:

#include<iostream>
#include<fstream>
#include<set>
using namespace std;
pair<int , int> p[3];
set<int> s;
bool is_use[30];
bool is_visit[20][20][20];
void dfs(int a , int b , int c,int step){
if(p[0].first == 0 && !is_use[p[2].first]){
s.insert(p[2].first);
is_use[p[2].first] = true;
}
if(step && is_visit[a][b][c])
return ;
is_visit[a][b][c] = true;
for(int i = 0 ;i < 3;i++){  //即将倒的瓶子
if(p[i].first == 0) continue;
for(int j = 0;j < 3;j++){   //即将被倒的瓶子
if(i != j){
if(p[i].first >= p[j].second - p[j].first){ //倒不满
int temp = p[j].first;
p[i].first -= p[j].second - p[j].first;
p[j].first = p[j].second;
dfs(p[0].first ,p[1].first , p[2].first, step + 1);
p[j].first = temp;
p[i].first += p[j].second - p[j].first;
}else if(p[i].first < p[j].second - p[j].first){ //不够倒
int temp = p[i].first;
p[j].first += p[i].first;
p[i].first = 0;
dfs(p[0].first ,p[1].first , p[2].first, step + 1);
p[i].first = temp;
p[j].first -= p[i].first;
}
}
}
}
is_visit[a][b][c] = false;  //回溯
}

int main(){
ofstream cout("milk3.out");
ifstream cin("milk3.in");
cin >> p[0].second >> p[1].second >> p[2].second;
p[1].first = 0;
p[2].first = 0;
p[2].first = p[2].second;
s.insert(p[2].first);
is_use[p[2].first] = true;
is_visit[0][0][p[2].first] = true;
dfs(0 , 0 , p[2].first , 0);
int len = s.size();
int i = 0;
for(set<int>::iterator it = s.begin() ; it != s.end(); it++,i++){
cout << *it;
if(i < len - 1)
cout << " "; //为了末尾没有空格
}
cout << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息