vijos p1412——多人背包

描述

DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包。这些包的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值。

在 DD 看来,合理的背包安排方案是这样的:

每个人背包里装的物品的总体积恰等于包的容量。 
每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。 
任意两个人,他们包里的物品清单不能完全相同。 
在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?

格式

输入格式

第一行有三个整数:K、V、N( 1 <= K <= 50, 0 <= V <= 5000,1 <= N <= 200 )。

第二行开始的 N 行,每行有两个整数,分别代表这件物品的体积和价值。

输出格式

只需输出一个整数,即在满足以上要求的前提下所有物品的总价值的最大值。

样例1

样例输入1

2 10 5
3 12
7 20
2 4
5 6
1 1

样例输出1

57

限制

各个测试点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 }

 

posted @ 2016-11-06 20:08  deadshotz  阅读(844)  评论(0编辑  收藏  举报