小Hi在游乐园中获得了M张奖券,这些奖券可以用来兑换奖品。
可供兑换的奖品一共有N件。第i件奖品需要Wi张奖券才能兑换到,其价值是Pi。
小Hi使用不超过M张奖券所能兑换到的最大奖品总价值是多少?
第一行两个整数N,M。
接下来N行,每行两个整数Wi,Pi。
对于 50%的数据: 1≤N,M≤1000
对于 100%的数据: 1≤N,M≤105,1≤Pi,Wi≤10。
一行一个整数,表示最大的价值。
3 10 2 3 8 8 10 10
11
多重背包二进制优化:将价值数量相同的物品分成1,2,4,8.。。因为100以内任何数都可以由几个2的n次方数组成。所以,有遍历没一个数变为遍历每一个2的n次方数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int N = 11000000;
int vis[105][105];
int w[N], v[N];
int dp[110000];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++)
{
int x, y;
scanf("%d %d", &x, &y);
vis[x][y]++;
}
int cnt=0;
memset(dp,0,sizeof(dp));
for(int i=0; i<=10; i++)
{
for(int j=0; j<=10; j++)
{
if(vis[i][j]==0) continue;
int k=1, num=vis[i][j];
while(num>k)
{
for(int h=m; h>=i*k; h--)
{
dp[h]=max(dp[h],dp[h-i*k]+j*k);
}
num-=k;
k<<=1;
}
for(int h=m; h>=i*num; h--)
{
dp[h]=max(dp[h],dp[h-i*num]+j*num);
}
}
}
printf("%d\n",dp[m]);
return 0;
}