Link
Problem
题目描述
农民约翰有三个容量分别是 a , b , c a,b,c a,b,c 升的桶。
最初, a , b a,b a,b 桶都是空的,而 c c c 桶是装满牛奶的。有时,农民把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。
当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。
写一个程序去帮助农民找出当 a a a 桶是空的时候, c c c 桶中牛奶所剩量的所有可能性。
输入格式
单独的一行包括三个整数 a , b , c a,b,c a,b,c。
输出格式
只有一行,升序地列出当 a a a 桶是空的时候, c c c 桶牛奶所剩量的所有可能性。
样例 #1
样例输入 #1
8 9 10
样例输出 #1
1 2 8 9 10
样例 #2
样例输入 #2
2 5 10
样例输出 #2
5 6 7 8 9 10
提示
【数据范围】
对于
100
%
100\%
100% 的数据,
1
≤
a
,
b
,
c
≤
20
1\le a,b,c \le 20
1≤a,b,c≤20。
题目翻译来自NOCOW。
USACO Training Section 1.4
Solution
这道题其实就是一个递归深搜,整体逻辑并不复杂,就是需要每次模拟六种倒法,即三个桶之间倒来倒去。
需要注意的是,一定要开一个三维数组判重,否则会MLE(大概是因为同样的答案存了很多份)
当然,我们还需要记录答案,这里作者用的是集合,当然用数组存也是没问题的
Code
#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
#define inf numeric_limits<ll>::max()/2
#define pb push_back
#define sz size
#define fi first
#define se second
#define mkp make_pair
#define pint pair<int,int>
#define pll pair<ll,ll>
#define gcd(a,b) b?gcd(b,a%b):a
#define lcm(a,b) a/(gcd(a,b))*b
#define low_bit(x) x&(-x)
using namespace std;
int A,B,C;
int vis[25][25][25];
set<int>st;
void dfs(int a,int b,int c){
if(vis[a][b][c])return ;
vis[a][b][c]=1;
if(a==0)st.insert(c);
if(b+a>B)dfs(a-(B-b),B,c);//把A倒入B
else dfs(0,b+a,c);
if(c+a>C)dfs(a-(C-c),b,C);//把A倒入C
else dfs(0,b,c+a);
if(a+b>A)dfs(A,b-(A-a),c);//把B倒入A
else dfs(a+b,0,c);
if(c+b>C)dfs(a,b-(C-c),C);//把B倒入C
else dfs(a,0,c+b);
if(a+c>A)dfs(A,b,c-(A-a));//把C倒入A
else dfs(a+c,b,0);
if(b+c>B)dfs(a,B,c-(B-b));//把C倒入B
else dfs(a,b+c,0);
}
signed main(){
cin>>A>>B>>C;
dfs(0,0,C);
set<int>::iterator it;
for(it=st.begin();it!=st.end();it++)cout<<*it<<' ';
return 0;
}
//ACplease!!!