1. 程式人生 > >[HAOI2012]音量調節

[HAOI2012]音量調節

三次 初始 遍歷 color col 背包 https 方程 onclick

題目鏈接

吐槽-沒看到可以調大調小,WA了一小時。很傷心,所以在此希望大家記得仔細讀題!!!

思考

01背包問題是 一個物品拿或者不拿中求最大值的問題

這道題目就是 音量增加或者減少中求最大值的問題

但是如果生搬硬套01背包的方程用在這裏肯定是不合適的。

在這裏,我們想對於每次調節,也就是兩種可能 在上次的基礎上調大,或者是調小。但是調大不能超過上限,調小不能超過下限。

讓我們再分析分析樣例:

3 5 10

5 3 7

第一次調節 只能從 5開始 調小的話就是0 調大的話就是10

第二次調節 先分析0 調小不可以 調大只能是3 在分析10 調小是7 調大不可以

第三次調節 先分析3 調小不可以 調大是10 再分析7 調小是0 調大是不可以

是不是隱隱約約能摸索出這個轉移方程了?

對沒錯,方程是 用二維bool型數組來DP,f[i][j]=true表示第i首歌音量為j可行,DP方程為:

if((f[i-1][j+c[i]]==true&&j+c[i]<=maxL)||(f[i-1][j-c[i]]==true&&j-c[i]>=0)) f[i][j]=true;

關鍵是f[i-1][j+c[i]] 和 f[i-1][j-c[i]]這兩個,要仔細推敲。

初始值f[0][初始值]=1

最後再從大到小遍歷 最後一次 調節時的最大值,如果存在輸出。如果不存在則輸出-1.

技術分享
 1
#include <cstdio> 2 const int maxn=1005; 3 int n,m,MAX,c[maxn]; 4 bool dp[maxn][maxn]; 5 int main(){ 6 scanf("%d%d%d",&n,&m,&MAX); 7 for(int i=1;i<=n;i++) scanf("%d",&c[i]); 8 dp[0][m]=1; 9 for(int i=1;i<=n;i++) 10 for(int j=0;j<=MAX;j++){
11 if( (dp[i-1][j+c[i]] && j+c[i]<=MAX) || ( dp[i-1][j-c[i]] && j-c[i]>=0)) 12 dp[i][j]=1; 13 } 14 for(int i=MAX;i>=0;i--){ 15 if(dp[n][i]) { 16 printf("%d\n",i); 17 return 0; 18 } 19 } 20 printf("-1"); 21 return 0; 22 }
代碼實現

[HAOI2012]音量調節