题 面 是 中 文 版 题面是中文版 题面是中文版
分析
个人认为这题非常考验对背包的理解!
我尝试把这道题讲清楚吧。
首先见到这题第一感觉就是NOIP2006金明的预算方案。把每一个主件的所有组合记录下来,然后进行分组背包,代码如下:
#include <bits/stdc++.h>
#define N 100005
using namespace std;
int f[N], cnt[55], w[55][1050], v[55][1050], p[11], q[11];
int main(){
int i, j, k, n, m, a, b, s1, s2;
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i++){
scanf("%d%d", &a, &b);
for(j = 0; j < b; j++) scanf("%d%d", &p[j], &q[j]);
for(j = 0; j < (1 << b); j++){
s1 = s2 = 0;
for(k = 0; k < b; k++){
if((1 << k) & j) s1 += p[k], s2 += q[k];
}
if(a + s1 > m) continue;
cnt[i]++;
w[i][cnt[i]] = a + s1;
v[i][cnt[i]] = s2;
}
}
for(i = 1; i <= n; i++){
for(j = m; j >= 0; j--){
for(k = 1; k <= cnt[i]; k++){
if(j >= w[i][k]) f[j] = max(f[j], f[j - w[i][k]] + v[i][k]);
}
}
}
printf("%d", f[m]);
return 0;
}
但是这是tle的!!!!
因为每个主件的组合数是 2 b 2^b 2b 个,最坏情况下复杂度高达 O ( 2 b ∗ N ∗ V ) O(2^{b}*N*V) O(2<