1. 程式人生 > 實用技巧 >【題解】P1858 多人揹包

【題解】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;
}