题意:
- 给你一个长度为m([1,2000])的长条状容器。
- 然后我们有n([1,1000])段木棒。
- 第i段木棒有一个长度a[i].l和价值a[i].v。
- 我们希望把尽可能大价值的木棒放到容器中,使得所有木棒的重心都在容器内
- 要求木棒不能重叠。
- 只有两端的木块可以省一半的长度(即重点放在端点上)
01背包变形,多了一维。
当我们无法判断哪个木块可以放在两端的时候,我们可以用状态来写。。。哎,挺简单的一道dp,但是不知道怎么处理两端的木块,就GG,挺好想到的。。。
以后遇到这种题的时候,用搜索的思维去想一发,即每个木块有两个决策, 放两端,不放两端。。。哎哎哎
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <cstdio>
#include <climits>
#define N 1005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll dp[4444][3];
struct node
{
int v,w;
}a[1111];
int main()
{
int T,i,j,n,m;
scanf("%d",&T);
for(int _=1;_<=T;_++) {
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&m);
m*=2;
for(i=1;i<=n;i++) {
scanf("%d%d",&a[i].v,&a[i].w);
a[i].v*=2;
a[i].w*=2;
}
printf("Case #%d: ",_);
if(n==1) {
printf("%d\n",a[1].w/2);
continue;
}
for(i=1;i<=n;i++) {
for(j=m;j>=a[i].v/2;j--) {
if(j>=a[i].v) {
dp[j][0]=max(dp[j][0],dp[j-a[i].v][0]+a[i].w);
dp[j][1]=max(dp[j][1],dp[j-a[i].v][1]+a[i].w);
dp[j][2]=max(dp[j][2],dp[j-a[i].v][2]+a[i].w);
}
dp[j][1]=max(dp[j][1],dp[j-a[i].v/2][0]+a[i].w);
dp[j][2]=max(dp[j][2],dp[j-a[i].v/2][1]+a[i].w);
}
}
printf("%lld\n",max(dp[m][0],max(dp[m][1],dp[m][2]))/2);
}
return 0;
}