洛谷P1877 [HAOI2012] 音量调节 题解
本题做法
- 0-1 背包 DP。
思路
定义 \(dp[i][j]\) 表示在前 $i 首歌曲是否可以达到音量 \(j\)(是的话为 \(\text{true}\),否则为 \(\text{false}\))。因为音量 \(j\) 可以由音量 \((j+c[i])\) 降低 \(c[i]\) 或者由音量 \((j-c[i])\) 升高 \(c[i]\) 转移而来,并且这 2 个音量只需要满足其中一个即可,所以需要用位运算“或”转移。
所以我们得到状态转移方程:
\[dp[i][j]=dp[i-1][j-c[i]]\text{ or }dp[i-1][j+c[i]]~(c[i]\le j\le maxLevel-c[i])
\]
根据此方程进行写 0-1 背包 DP 代码就行了。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=55;
const int V=1005;
ll n,c[N],beg,maxx;
bool dp[N][V];
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin>>n>>beg>>maxx;
for(int i=1;i<=n;i++) cin>>c[i];
dp[0][beg]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=maxx;j++){
if(j-c[i]>=0) dp[i][j]|=dp[i-1][j-c[i]];
if(j+c[i]<=maxx) dp[i][j]|=dp[i-1][j+c[i]];
}
}
for(int i=maxx;i>=0;i--){
if(dp[n][i]==1){
cout<<i<<endl;
return 0;
}
}
cout<<-1<<endl;
return 0;
}

浙公网安备 33010602011771号