背包九讲之二(完全背包)

 1 /*

 2 有n种物品和一个容量为v的背包,每件物品可以无限使用,

 3 第i件物品的费用为c[i],价值为w[i],求解哪些物品装入背包

 4 费用不超过背包容量且价值总和最大

 5 基本思路是dp[i][j] = max{dp[i-1][j-k*c[i]] k*c[i]<=j}

 6 和01背包一样有V*N个状态,但是每个状态的求解不再是O(1)了,

 7 求解状态dp[i][j]是O(j/c[i]),总的时间复杂度超过O(V*N)

 8 

 9 可以转化为01背包问题从而求解

10 (1)第i件物品可以转化为v/c[i]件物品,从而转化为01背包问题

11 (2)一种更加好的方法是将第二种物品转化为费用c[i]*2^k,价值w[i]*2^k

12     的若干件物品,其中k满足c[i]*2^k<=v.这是二进制的思想。因为不管最优策选择

13     几件第i中物品,都可以用若干个2^k件物品来表示,这样就把每种物品拆分为

14     log(v/c[i])种物品

15 

16 但是有更优的O(VN)算法

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

18     for(j=v[i]; j<=v; ++j)

19         dp[j] = max(dp[j],dp[j-c[i]+w[i]);

20 

21 其实可以这么想  dp[i][j] = max(dp[i-1][j],dp[i][j-v[i]]+w[i]);

22 dp[i][j]可以转化为上一层的dp[i-1][j],也可以转化为这一层左边的状态

23 所以要求比j小的状态要算出来,所以要求j从0-->v

24 就是

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

26     for(j=0; j<=v; ++j)

27     {

28         dp[i][j] = dp[i-1][j];

29         if(j>=v[i])

30             dp[i][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);

31     }

32 转化为一维的状态就是

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

34 for(j=v[i]; j<=v; ++j)

35     dp[j] = max(dp[j],dp[j-c[i]]+w[i]);

36 */

37 #include <stdio.h>

38 #include <string.h>

39 int dp[111][1111];

40 int dp2[1111];

41 int c[111],w[111];

42 inline int max(const int &a, const int &b)

43 {

44     return a < b ? b : a;

45 }

46 int main()

47 {

48     int n,v,i,j,k;

49     while(scanf("%d%d",&n,&v)!=EOF)

50     {

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

52             scanf("%d",&w[i]);

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

54             scanf("%d",&c[i]);

55         memset(dp,0,sizeof(dp));

56         memset(dp2,0,sizeof(dp2));

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

58         {

59             for(j=0; j<=v; ++j)

60             {

61                 dp[i][j] = dp[i-1][j];

62                 if(j>=c[i])

63                 {

64                     dp[i][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);

65                     dp2[j] = max(dp2[j],dp2[j-c[i]]+w[i]);

66                 }

67             }                

68         }

69         

70         printf("%d\n",dp[n][v]);

71         printf("%d\n",dp2[v]);

72     }

73     return 0;

74 }

75 

76 /*

77 sample input:

78 5 10

79 1 2 5 4 6

80 2 2 6 5 4

81 

82 sample output:

83 

84 */

 

你可能感兴趣的:(背包)