51nod-1086 Backpack problem V2

Baseline Time Limit: 1 second Space Limit: 131072 KB Score: 40  Difficulty: Level 4 Algorithm Questions
 collect
 focus on
There are N items, and each item has a quantity of C1, C2...Cn. Choose a number of them and put them in a backpack with a capacity of W. The volume of each item is W1, W2...Wn (Wi is an integer), and the corresponding value is P1, P2.... ..Pn (Pi is an integer). Find the maximum value the backpack can hold.
Input
Line 1, 2 integers, N and W separated by a space. N is the type of item, and W is the capacity of the backpack. (1 <= N <= 100, 1 <= W <= 50000)
Lines 2 - N + 1, 3 integers per line, Wi, Pi and Ci are item volume, value and quantity respectively. (1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
Output
The maximum value the output can hold.
Input example
3 6
2 2 5
3 3 8
1 4 1
Output example
9

Problem solution: A typical multiple knapsack problem, for a certain item, it can be decomposed into 01 knapsack problem and solved. But this question will do T. We noticed that for any item with C quantity in the multi-knapsack, we only need to obtain its range (0 ~ C), so we can perform binary decomposition;

Suppose C = 1 + 2 + 4 + . . . . + 2 ^m + k(k < 2 ^(m + 1)); then only 1 .. 2 .. 4 ..... 2^m..k is a random combination of m + 1 numbers Get any number from 0 to C (1 .. 2 .. 4 ..... 2^m to get any number from 0 to 2^(m + 1), the lower bound remains unchanged after adding k, and the upper bound becomes C). This reduces the complexity from O(C * W * N) to O(log(C) * W * N).

Ac code

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
 
using namespace std;

const int maxn = 55555;
int dp[maxn], num[maxn];

struct node{
	int w, p, c;
}p[111];

int main(){
	int n, w;
	scanf("%d%d", &n, &w);
	for(int i = 0; i < n; i++)
		scanf("%d %d %d", &p[i].w, &p[i].p, &p[i].c);
	for(int i = 0; i <= w; i++)
		dp[i] = 0;
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= w; j++)
			num[j] = 0;
		int c = p[i].c;
		for(int j = 1; j < c; j <<= 1){
			for(int k = w; k - p[i].w * j >= 0; k--)
				dp[k] = max(dp[k], dp[k - p[i].w * j] + j * p[i].p);
			c -= j;
		}
		int j = c;
		for(int k = w; k - p[i].w * j >= 0; k--)
			dp[k] = max(dp[k], dp[k - p[i].w * j] + j * p[i].p);
		
	}
	printf("%d\n", dp[w]);
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325991378&siteId=291194637