题意:给定n个长度为v[i], 价值为w[i]的木棍,问在总长度不超过l的情况下最大价值是多少。限制条件是:两端的木棍可以一半在长度范围内,一半在外面。
,,,快把评测姬wa穿了也没做出来,,白做那么多揹包的题了,,,生气
思路:最多两个木棍可以一半长度在里面,那么放长度为一半的木棍的时候必须确保状态转移的时候不能从之前放的已经有两个木棍放了一半的情况下转移,,我试图用一维dp做,,结果,我不wa谁wa。
dp[j][k]表示揹包剩余容量为j,放了k个一半长度的木棍在揹包里的最大价值
(0<=j<=l, 0<=k<3)
但是还有一个问题,如果木棍长度为奇数,我们让v[i]/2在里面还是v[i]/2+1在里面?事实上都不对,,,它的一半就是准准确确的一半,那么就把所有的长度都乘以2,就不会出现这种问题了。(我为啥就想不到,枯了)
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 2005;
ll v[N],dp[N<<1][5],w[N];
int main()
{
int t,cas=1;
cin>>t;
while(t--)
{
int n,l;
ll ans=0;
cin>>n>>l;
l*=2;
for(int i=0;i<n;i++) scanf("%lld%lld",&v[i],&w[i]),v[i]*=2;
memset(dp,0,sizeof dp);
for(int i=0;i<n;i++)
{
for(int j=l;j>=0;j--)
for(int k=0;k<3;k++)
{
if(j>=v[i])
dp[j][k]=max(dp[j][k],dp[j-v[i]][k]+w[i]);
if(k&&j>=v[i]/2)
dp[j][k]=max(dp[j][k],dp[j-v[i]/2][k-1]+w[i]);
}
}
for(int i=0;i<n;i++) ans=max(ans,w[i]);
for(int k=0;k<3;k++)
ans=max(ans,dp[l][k]);
printf("Case #%d: ",cas++);
cout<<ans<<endl;
}
return 0;
}