题意
- 给你n个小木棍,每根有长度和权值,一维的把它们放到一个长为L的平台上,只要木棍重心在平台上,即可认为可以放上去,问你怎么放,权值最高。
- n<=1000, L <= 2000
思路
- 在0,1背包的基础上加一维,维护两端放出去的木棍现在有几个
- 求出后在和考虑只放一根木棍的情况,和n个木棍的权值求max即可
- 注意的是,要想到取一半的时候有小数的问题,所以预先把所有长度乘二。
实现
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 1005;
const int maxl = 4005;
typedef long long ll;
int n,l;
int a[maxn];
int v[maxn];
ll dp[maxl][3];
int main(){
int T;
cin>>T;
for (int t=1;t<=T;t++){
scanf("%d%d",&n,&l);
l <<= 1;
for (int i=1;i<=n;i++){
scanf("%d%d",&a[i],&v[i]);
a[i] <<= 1;
}
memset(dp,0,sizeof(dp));
for (int i=1;i<=n;i++){
int tmp = (a[i] >> 1);
for (int j=l;j>=tmp;j--){
for (int k=0;k<3;k++){
if (j >= a[i]){
dp[j][k] = max(dp[j][k],dp[j-a[i]][k] + (ll)v[i]);
}
if (k > 0){
dp[j][k] = max(dp[j][k],dp[j-tmp][k-1] + (ll)v[i]);
}
}
}
}
ll ans = 0;
for (int i=1;i<=n;i++){
ans = max(ans,(ll)v[i]);
}
ans = max(ans,dp[l][2]);
printf("Case #%d: %lld\n",t,ans);
}
return 0;
}