完全背包问题:湫湫系列故事――减肥记I(HDU 4508)

湫湫系列故事――减肥记I  HDU 4508

一道裸的完全背包

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<stdio.h>
 4 #include<string.h>
 5 using namespace std;
 6 int c[100005],a[105],b[105];
 7 int main()
 8 {
 9     int n,i,j,m;
10     while(scanf("%d",&n)!=EOF)
11     {
12         for(i=0;i<n;i++)
13             scanf("%d%d",&a[i],&b[i]);
14         scanf("%d",&m);
15         memset(c,0,sizeof(c));
16         for(i=0;i<n;i++)
17             for(j=b[i];j<=m;j++)
18                 if(c[j]<c[j-b[i]]+a[i])
19                 c[j]=c[j-b[i]]+a[i];
20         printf("%d\n",c[m]);
21     }
22     return 0;
23 }

 下面是没有二进制优化的算法:

思路:

这个问题非常类似于01背包问题,所不同的是每种物品有无限件。也就是从每种物品的角度考虑,与它相关的策略已并非取或不取两种,而是有取0件、取1件、取2件……直至取⌊V/Ci⌋件等许多种。
如果仍然按照解01背包时的思路,令F[i,v]表示前i种物品恰放入一个容量为v的背包的最大权值。仍然可以按照每种物品不同的策略写出状态转移方程,像这样:
F[i,v]=max{F[i−1,v−kCi]+kWi|0≤kCi≤v}
这跟01背包问题一样有O(VN)个状态需要求解,但求解每个状态的时间已经不
是常数了,求解状态F[i,v]的时间是O(vCi),总的复杂度可以认为是O(NVΣVCi),是比较大的。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<stdio.h>
 4 #include<string.h>
 5 using namespace std;
 6 int c[100005],a[105],b[105];
 7 int main()
 8 {
 9     int n,i,j,k,m;
10     while(scanf("%d",&n)!=EOF)
11     {
12         for(i=0;i<n;i++)
13             scanf("%d%d",&a[i],&b[i]);
14         scanf("%d",&m);
15         memset(c,0,sizeof(c));
16         for(i=0;i<n;i++)
17             for(k=0;k<=m/b[i];k++)//数量
18             for(j=m;j>=k*b[i];j--)
19             c[j]=max(c[j],c[j-k*b[i]]+k*a[i]);
20         printf("%d\n",c[m]);
21     }
22     return 0;
23 }

 

posted on 2013-08-25 10:20  ~~碾压机  阅读(166)  评论(0编辑  收藏  举报