题目描述
Blice和阿强巴是好朋友
但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习
阿强巴有 头奶牛,每头奶牛每天可以产一定量的奶,同时也需要一定量的草作为饲料
对于第 头奶牛来说,它每天可以产 升的奶,同时需要 千克的草作为饲料
现在来自蚯蚓国的九条可怜想借一些奶牛,使借走的这些奶牛每天的总产奶量最大,但九条可怜很穷,每天最多只能提供
千克的草作为饲料,而且她还需要对付跳蚤国的神刀手,所以她把这个问题交给了阿强巴,不不不……阿强巴觉得这个
问题太简单了,所以把这个问题交给了你
输入格式
第一行两个整数 ,表示奶牛的数量和每天最多能提供的草
接下来 行,每行两个整数,第 行表示第 头奶牛的产奶量 和食量
输出格式
仅一行,输出一个整数,表示每天最大的总产奶量
输入样例
8 40
10 9
12 11
11 12
10 10
8 11
7 9
8 10
9 10
输出样例
41
限制与约定
对于 的数据,
另有 的数据,
另有 的数据,
对于 的数据,
对于所有数据,均满足特殊限制:
n
i vi wi
W
n,W
n i i vi wi
20% n ≤ 10
30% W ≤ 10000
10% wi = w1
100% 1 ≤ n ≤ 100,1 ≤ wi,W ≤ 109
,1 ≤ vi ≤ 10
7
w1 ≤ wi ≤ w1 + 3
一看便是01背包的题目,但是题中W会很大,普通的背包肯定不行了,但是
观察到wi的变化不超过3
令base=w1,然后把所有的wi减去base
设计状态f[i][j][k]表示DP到第i个奶牛时,选了j个奶牛,这j个奶牛(减去base之后的)w_i的和为k
就是对01背包简单做一下变形
时间复杂度O(n^3),空间复杂度O(n^3)或O(n^2)
第一维可以优化,不过对时间复杂度没有影响
记忆化搜索
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,lim;
int f[105][105][305],w[105],v[105];
char vis[105][105][305];
int dp(int i,int j,int k)
{
if (1LL*j*lim+k>m) return -2e9;//如果k>m-j*lim显然是超过背包容量的。舍去
if (i==n) return 0;
if (f[i][j][k]) return f[i][j][k];//记忆化搜索
return f[i][j][k]=max(dp(i+1,j,k),dp(i+1,j+1,k+w[i+1])+v[i+1]);
}
main()
{
//freopen("backpack.in","r",stdin);
//freopen("backpack.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d%d",v+i,w+i);
lim=w[1];
for (int i=1;i<=n;++i) w[i]-=lim;
printf("%d\n",dp(0,0,0));
return 0;
}