描述
DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包。这些包的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值。
在 DD 看来,合理的背包安排方案是这样的:
每个人背包里装的物品的总体积恰等于包的容量。
每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。
任意两个人,他们包里的物品清单不能完全相同。
在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?
格式
输入格式
第一行有三个整数:K、V、N( 1 <= K <= 50, 0 <= V <= 5000,1 <= N <= 200 )。
第二行开始的 N 行,每行有两个整数,分别代表这件物品的体积和价值。
输出格式
只需输出一个整数,即在满足以上要求的前提下所有物品的总价值的最大值。
限制
各个测试点1s
先看数据范围,算法时间复杂度应该是O(kvn)
考虑DP,此题为01背包装满,唯一不同的是等于背包重量所选的物品不能和另一个背包重复
考虑f[j][k],表示j重量的第k优的结果
于是f[j]可以从f[j]和f[j-w[i]]推来,通过比较更新出前k优的值
最后ans依次加,即为重量为v的前k优的各个价值和
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxk=55;
4 const int maxv=5005;
5 const int maxn=205;
6 int f[maxv][maxk];
7 int t[maxv];
8 int v[maxn],w[maxn];
9 int k,m,n;
10 void solve(int a[],int b[],int c)
11 {
12 int i=1;
13 int j=1;
14 int pos=1;
15 while(i+j<=k+1)
16 {
17 if(a[i]>b[j]+c)t[pos++]=a[i++];
18 else t[pos++]=b[j++]+c;
19 }
20 for(int i=1;i<=k;i++)
21 a[i]=t[i];
22 }
23 int main()
24 {
25 freopen("1.in","r",stdin);
26 freopen("1.out","w",stdout);
27 memset(f,128,sizeof(f));
28 scanf("%d%d%d",&k,&m,&n);
29 for(int i=1;i<=n;i++)
30 scanf("%d%d",&v[i],&w[i]);
31 f[0][1]=0;
32 for(int i=1;i<=n;i++)
33 {
34 for(int j=m;j>=v[i];j--)
35 solve(f[j],f[j-v[i]],w[i]);
36 }
37 long long ans=0;
38 for(int i=1;i<=k;i++)
39 ans+=f[m][i];
40 printf("%I64d",ans);
41 return 0;
42 }