【题解】P1858 多人背包

P1858 多人背包

题目描述

求01背包前k优解的价值和
DD 和好朋友们要去爬山啦!
他们一共有 K 个人,每个人都会背一个包。这些包 的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有 给定的体积和价值。
在 DD 看来,合理的背包安排方案是这样的: 每个人背包里装的物品的总体积恰等于包的容量。 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。
任意两个人,他们包里的物品清单不能完全相同。 在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?

输入格式

第一行三个数K、V、N
接下来每行两个数,表示体积和价值

输出格式

前k优解的价值和

输入输出样例

输入 #1

2 10 5
3 12
7 20
2 4
5 6
1 1
输出 #1

57

说明/提示

对于100%的数据,

K≤50,V≤5000,N≤200

题解

很多很多人,意思就是体积一样但是有很多很多不同的方案

状态:
$ f[i][j][k] $ 前i个人,体积为j,第k大的价值
决策:第i个物品选不选
归并转移

code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>


using namespace std;

int k , V , n , ans;
int w[210] , v[210];
int now[55];
int  f[5010][210] ;

int main()
{
	cin >> k >> V >> n;
	for (int i = 1 ; i <= n ; i++)
	{
		cin >> w[i] >> v[i];
	}
	for (int i = 0 ; i <= V ; i++)
	{
		for (int j = 1 ; j <= k ; j++)	f[i][j] = -10000;
	}
	f[0][1] = 0;//体积为零时最优价值为0
	//第2优、第3优、··第k优都要负无穷 
	for (int i = 1 ; i <= n ; i++)
	{
		for (int j = V ; j >= w[i] ; j--)
		{
			int cnt = 0 , c1 = 1 , c2 = 1;
			while(cnt <= k)
			{
				if(f[j][c1] >= f[j - w[i]][c2] + v[i])
					now[++cnt] = f[j][c1++];
				else
					now[++cnt] = f[j - w[i]][c2++] + v[i];
			}
			for (int c = 1 ; c <= k ; c++)
			{
				f[j][c] = now[c];			
        	}
		}
	}
	for (int i = 1 ; i <= k ; i++)
		ans += f[V][i];
	cout << ans << endl;
	return 0;
}
posted @ 2020-08-23 14:50  _Buffett  阅读(161)  评论(0编辑  收藏  举报