您的位置:首页 > 其它

FZU Problem 2214 Knapsack problem(01背包,超大背包)——第六届福建省大学生程序设计竞赛-重现赛

2016-09-08 15:33 507 查看
此文章可以使用目录功能哟↑(点击上方[+])




 FZU Problem 2214 Knapsack problem

Accept: 0    Submit: 0

Time Limit: 3000 mSec    Memory Limit : 32768 KB




 Problem Description

Given a set of n items, each with a weight w[i] and a value v[i], determine a way to choose the items into a knapsack so that the total weight is less than or equal to a given limit B and the total value is as large as possible. Find the maximum total value.
(Note that each item can be only chosen once).



 Input

The first line contains the integer T indicating to the number of test cases.

For each test case, the first line contains the integers n and B.

Following n lines provide the information of each item.

The i-th line contains the weight w[i] and the value v[i] of the i-th item respectively.

1 <= number of test cases <= 100

1 <= n <= 500

1 <= B, w[i] <= 1000000000

1 <= v[1]+v[2]+...+v
<= 5000

All the inputs are integers.



 Output

For each test case, output the maximum value.



 Sample Input

1

5 15

12 4

2 2

1 1

4 10

1 2



 Sample Output

15



 Hint



 Problem Idea

解题思路:

【题意】
有n件商品,和一个容量为B的背包

已知这n件商品每件的重量和价值

现要从中选取一些商品

问在不超过背包容量的前提下,所能获得的最大价值为多少

【类型】
01背包,超大背包

【分析】

很显然,这是一道01背包的动规题

但是,仔细看一下数据范围之后,发现又不是那么纯粹的01背包

我们知道,对于01背包的题,在用一维数组实现求解的时候,时间复杂度为O(n×B),空间复杂度为O(B)

常规做法DP部分代码如下:

for(i=0;i<n;i++)
for(j=B;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
而此题B的大小范围为1 ≤ B ≤ 1000000000

由此可见,无法直接使用01背包,因为背包的容量过大

那要怎么来做呢?

继续看题,发现1 ≤ v[1]+v[2]+...+v
≤ 5000

奇怪,平时遇到01背包的题,都是不限定价值范围的(≤10^9这种除外)

而此题给了这个限制,肯定,问题的关键在此

思考一下,可以发现这样一种解法

将价值之和看作是背包容量,这样此题的做法就是

尽可能塞满背包的情况下,使得商品重量之和尽可能小

那么在满足重量之和小于B的条件下,价值之和最大的即为此题的解

DP部分代码如下:

for(i=0;i<n;i++)
for(j=sum;j>=v[i];j--)
dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
【时间复杂度&&优化】



题目链接→FZU Problem 2214 Knapsack problem



 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define PI acos(-1.0)
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 505;
const int M = 5005;
const int inf = 1000000007;
const int mod = 1000003;
int w
,v
,dp[M];
int main()
{
int t,n,B,i,j,sum;
scanf("%d",&t);
while(t--)
{
sum=0;
scanf("%d%d",&n,&B);
for(i=0;i<n;i++)
{
scanf("%d%d",&w[i],&v[i]);
sum+=v[i];
}
for(i=0;i<=sum;i++)
dp[i]=inf;
dp[0]=0;
for(i=0;i<n;i++)
for(j=sum;j>=v[i];j--)
dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
for(i=sum;i>=0;i--)
if(dp[i]<=B)
break;
printf("%d\n",i);
}
return 0;
}
菜鸟成长记
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐