FZU - 2214 Knapsack problem (零一揹包 變形)

iven 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[n] <= 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

剛看發現是01揹包板子題,興奮的敲一發,RE,wtf……(''^_^)!!

題目w太大會導致數組溢出。不過注意到價值的數據較小。可以將物品的價值和體積位置調換,dp[j]的含義改變爲裝價值爲j的的物品,至少需要多大的容量。運用揹包求解(注意:此處的01揹包要求恰好裝滿),求出最後各個價值所需的最小容量,然後通過與限制B進行比較,求出最大容量。

初始化問題:有的題目要求“恰好裝滿揹包”時的最優解,有的題目則並沒有要求必須把背 包裝滿。如果是第一種問法,要求恰好裝滿揹包,那麼在初始化時除了F[0]爲0,其 它F[1..V ]均設爲−∞,這樣就可以保證最終得到的F[V ]是一種恰好裝滿揹包的 最優解。 如果並沒有要求必須把揹包裝滿,而是隻希望價格儘量大,初始化時應該 將F[0..V ]全部設爲0
 

/*

*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <set>
#include <bitset>
#include <stack>
#define ull unsigned long long
#define mems(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const ll mod=100000007;
const double pi=acos(-1);
const int N=200007;
int a[5009],w[5009],v[5008];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
       mems(a,inf);
       a[0]=0;
       ll sum=0;
       int n,m;
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)
       {
           scanf("%d%d",&w[i],&v[i]);
           sum+=v[i];
       }
       for(int i=1;i<=n;i++)
       {
           for(int j=sum;j>=v[i];j--)
            a[j]=min(a[j],a[j-v[i]]+w[i]);
       }
       for(int j=sum;j>=0;j--)
       {
           if(a[j]<=m)
           {
               printf("%d\n",j);
               break;
           }
       }
    }
    return 0;
}
/*

*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章