0,1 背包问题,赛后听了秦总队友的讲解会了。增加一维:
dp[k][i][v] :
第一维:
k=0,1,2
。
0
代表没有半截的情况,
第二维:前
第三位:占了
v
容量。
那么
dp[0][i][v]=max(dp[0][i−1][v],dp[0][i−1][v−c[i]]+w[i])dp[1][i][v]=max(dp[1][i−1][v],dp[1][i−1][v−c[i]]+w[i],dp[0][i−1][v−c[i]2]+w[i])dp[2][i][v]=max(dp[2][i−1][v],dp[2][i−1][v−c[i]]+w[i],dp[1][i−1][v−c[i]2]+w[i])
小
trick
:
1
:对于容量
2
:只放
代码:
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
const int Mod = 1000000007;
const int maxN = 1010;
const int maxL = 4040;
LL dp[3][maxL];
int n,l,c[maxN],w[maxN];
void init(){
scanf("%d%d",&n,&l);
l <<= 1;
FOR(i,1,n+1){
scanf("%d%d",&c[i],&w[i]);
c[i] <<= 1;
}
memset(dp,0,sizeof(dp));
}
LL DP0(int i,int v){
LL res = dp[0][v];
if(v >= c[i]) res = max(res,dp[0][v-c[i]]+w[i]);
return res;
}
LL DP1(int i,int v){
LL res = dp[1][v];
if(v >= (c[i]+1)/2){
res = max(res,dp[0][v-c[i]/2]+w[i]);
if(v >= c[i]){
res = max(res,dp[1][v-c[i]]+w[i]);
}
}
return res;
}
LL DP2(int i,int v){
LL res = dp[2][v];
if(v >= (c[i]+1)/2){
res = max(res,dp[1][v-c[i]/2]+w[i]);
if(v >= c[i]){
res = max(res,dp[2][v-c[i]]+w[i]);
}
}
return res;
}
void work(){
FOR(i,1,n+1){
IFOR(v,l,0){
dp[0][v] = DP0(i,v);
dp[1][v] = DP1(i,v);
dp[2][v] = DP2(i,v);
}
}
LL t = -1;
FOR(i,1,n+1) t = max(t,(LL)w[i]);
printf("%lld\n",max(dp[2][l],t));
}
int main(){
//freopen("test.in","r",stdin);
int T,tCase = 0; scanf("%d",&T);
while(T--){
printf("Case #%d: ",++tCase);
init();
work();
}
return 0;
}