I. Steadily Growing Steam
题链
看完题发现可以暴力dp
最开始想的状态就是dp[i][j][k]就是左边已经i权重右边已经j权重并且用了k次乘二的maxv
然后我们时间复杂度算接近1e10左右 当时想的感觉2的次数不会太多 就在那里试了很多发
最后发现我们不必要记录两堆的权值 我们只要记录他们之差就可以了
然后dp[i][k]就是dp[i][k]相差i然后用了k次乘2
然后我们转移就只有5种
1.不选这一个 dp[i][k][x&1]=max{dp[i][k][x&1^1]}
2.选 但是不乘2 dp[i][k][x&1]=max{dp[i-w][k][x&1^1]} dp[i][k][x&1]=max{dp[i+w][k][x&1^1]}
3.选 但是乘2 dp[i][k][x&1]=max{dp[i-2w][k][x&1^1]} dp[i][k][x&1]=max{dp[i+2*w][k][x&1^1]}
最后答案就是dp[0][j][n&1]
int dp[1510][110][2];
void solve(){
int n,k;cin>>n>>k;
memset(dp,-0x3f3f,sizeof dp);
dp[0][0][0]=0;
for(int i=1;i<=n;i++) {
int w, v;
cin >> v >> w;
for (int j = 1500; j >= 0; j--) {
for (int q = 0; q <= k; q++) {
dp[j][q][i & 1] = max(dp[j][q][i & 1],dp[j][q][i & 1 ^ 1]);
if (dp[j][q][i & 1 ^ 1] >= -INF / 2) {
if (j + 2 * w <= 1500)
dp[j + 2 * w][q + 1][i & 1] = max(dp[j + 2 * w][q + 1][i & 1], dp[j][q][i & 1 ^ 1] + v);
if (j + w <= 1500)dp[j + w][q][i & 1] = max(dp[j + w][q][i & 1], dp[j][q][i & 1 ^ 1] + v);
dp[abs(j - 2 * w)][q + 1][i & 1] = max(dp[abs(j - 2 * w)][q + 1][i & 1], dp[j][q][i & 1 ^ 1] + v);
dp[abs(j - w)][q][i & 1] = max(dp[abs(j - w)][q][i & 1], dp[j][q][i & 1 ^ 1] + v);
}
}
}
}
int ans=-INF;
for(int j=0;j<=k;j++)ans=max({ans,dp[0][j][0],dp[0][j][1]});
cout<<ans<<endl;
}
标签:Regional,Contest,int,max,Shanghai,Asia,dp
From: https://www.cnblogs.com/ycllz/p/16948760.html