您的位置:首页 > 其它

学习笔记:vijos1412[多人背包] 背包k优解...

2017-07-12 09:04 176 查看

描述

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

来源

感谢dd_engi

懵逼题解

看到这个题我的内心突然就蹦出来在原数组f[j]里加一个优先队列 表示在剩余体积为j时能达到的第1.2.3…k优解

然后考虑考虑 可能爆时间(nvklgk)

后来看网上说 实际上选与不选的两个队列都是有序的 所以可以用归并的方法 来合并f[j][1~k]和f[j-a[i].c][1~k]+a[i].w

然后算了算复杂度o(nvk)

试着写了写 居然没挂╮(╯_╰)╭

#include<cstdio>
#include<cstring>
#define MAXN (200+5)
#define MAXV (5000+5)
#define MAXK (50+5)
#define INF (0x7ffffff)
using namespace std;
struct bp
{
int c;
int w;
}a[MAXN];
int f[MAXV][MAXK];//f[j][k]表示在剩余体积为j的情况下,第k优解的价值
int n,k,v;
int main()
{
scanf("%d%d%d",&k,&v,&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].c,&a[i].w);
}
for(int i=0;i<=v;i++)
{
for(int j=1;j<=k;j++)
{
f[i][j]=-INF;//初始化,表示f[i][j]未算过
}
}
int t[MAXK];//归并时的中间数组
int l1,l2;//两个有序数列的队首
f[0][1]=0;//初始化,什么都没有选的话最优解为0
for(int i=1;i<=n;i++)//同01背包
{
for(int j=v;j>=a[i].c;j--)
{
if(f[j-a[i].c][1]>=0)//如果f[j-a[i].c][1~k]有算过
{
l1=1;//开始归并
l2=1;
for(int z=1;z<=k;z++)
{
if((f[j-a[i].c][l1]+a[i].w)>f[j][l2])
{
t[z]=f[j-a[i].c][l1++]+a[i].w;
}
else
{
t[z]=f[j][l2++];
}
}
for(int z=1;z<=k;z++)
{
f[j][z]=t[z];//把中间数组的值赋值回原数组
}
}
}
}
int ans=0;
for(int i=1;i<=k;i++)
{
ans+=f[v][i];
}
printf("%d",ans);
return 0;
}


by 萌萌哒Cansult

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  背包k优解 01背包