USACO 5.3 Milk Measuring(迭代深搜+DP)

像是背包的逆问题,给一个体积,然后给一些物品,求用最少的物品组成这个体积,输出字典序最小的集合。

物品和体积都不小,完全没什么思路,印象中DD大神的背包9讲里,有USACO里背包问题的解析,然后发现暴力然后DP就可以过,然后。。。就水过了。。

 1 /*

 2 ID: cuizhe

 3 LANG: C++

 4 TASK: milk4

 5 */

 6 #include <cstdio>

 7 #include <cstring>

 8 #include <cmath>

 9 #include <algorithm>

10 #include <iostream>

11 using namespace std;

12 int v;

13 int p[101];

14 int o[101];

15 int que[101];

16 int dp[20001];

17 int t,n;

18 int dfs(int x)

19 {

20     int i,j;

21     if(x == 0)

22     {

23         for(i = 1;i <= v;i ++)

24         dp[i] = 0;

25         for(i = 1;i <= t;i ++)

26         {

27             for(j = p[que[i]];j <= v;j ++)

28             dp[j] = max(dp[j],dp[j-p[que[i]]]+p[que[i]]);

29         }

30         if(dp[v] == v)

31         return 1;

32         else

33         return 0;

34     }

35     for(i = 1;i <= n;i ++)

36     {

37         if(!o[i])

38         {

39             o[i] = 1;

40             que[x] = i;

41             if(dfs(x-1))

42             return 1;

43             o[i] = 0;

44         }

45     }

46     return 0;

47 }

48 int main()

49 {

50     int i,j;

51     freopen("milk4.in","r",stdin);

52     freopen("milk4.out","w",stdout);

53     scanf("%d%d",&v,&n);

54     for(i = 1;i <= n;i ++)

55     scanf("%d",&p[i]);

56     sort(p+1,p+n+1);

57     for(i = 1;i <= n-1;i ++)

58     {

59         memset(o,0,sizeof(o));

60         t = i;

61         if(dfs(i))

62         break;

63     }

64     printf("%d",i);

65     if(i == n)

66     {

67         for(i = 1;i <= n;i ++)

68         printf(" %d",p[i]);

69     }

70     else

71     {

72         for(j = i;j >= 1;j --)

73         printf(" %d",p[que[j]]);

74     }

75     printf("\n");

76     return 0;

77 }

 

你可能感兴趣的:(USACO)