USACO 5.3 Milk Measuring(ID-DFS,DP)
2015-03-30 11:53:27
思路:题意看了我好久... TAT 英语太渣辣
简而言之就是用一些不同容量的桶装牛奶,倒在一个大瓶中获得一个要求的总体积,每个桶可装无限次牛奶。要求桶尽量少。
显然不知道最终需要多少桶,盲目的dp会tle,所以考虑用ID-DFS(迭代加深搜索)。
其实很简单,就是枚举使用的桶的数量,然后用DFS枚举使用哪些桶,随后用完全背包来检查用这些桶能否构成这个总体积即可。
(加了一个小剪枝,DFS中,如果根据当前已经取的桶的数量,后面的全部都取都不够当前枚举的桶的数量,那么停止搜索)
1 /* 2 ID:naturec1 3 PROG: milk4 4 LANG: C++ 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <cstdlib> 9 #include <cmath> 10 #include <vector> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <string> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 20 #define MEM(a,b) memset(a,b,sizeof(a)) 21 #define REP(i,n) for(int i=0;i<(n);++i) 22 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 23 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 24 #define MP(a,b) make_pair(a,b) 25 26 typedef long long ll; 27 typedef pair<int,int> pii; 28 const int INF = (1 << 30) - 1; 29 30 int Q,P; 31 int v[110]; 32 int k; 33 int cur_p[110]; 34 bool dp[20010]; 35 36 bool Judge(){ 37 MEM(dp,false); 38 dp[0] = true; 39 REP(i,k){ 40 for(int j = cur_p[i]; j <= Q; ++j) 41 dp[j] |= dp[j - cur_p[i]]; 42 } 43 return dp[Q]; 44 } 45 46 bool Dfs(int p,int num){ 47 if(p >= P){ 48 if(num != k) return false; 49 if(Judge()) return true; 50 return false; 51 } 52 cur_p[num] = v[p]; 53 if(num < k && Dfs(p + 1,num + 1)) return true; 54 if(num + P - p - 1 >= k && Dfs(p + 1,num)) return true; 55 return false; 56 } 57 58 int main(){ 59 freopen("milk4.in","r",stdin); 60 freopen("milk4.out","w",stdout); 61 scanf("%d",&Q); 62 scanf("%d",&P); 63 REP(i,P) scanf("%d",&v[i]); 64 sort(v,v + P); 65 for(k = 1; k <= P; ++k){ 66 if(Dfs(0,0)){ 67 printf("%d",k); 68 REP(i,k) printf(" %d",cur_p[i]); 69 puts(""); 70 break; 71 } 72 } 73 return 0; 74 }