牛客 --- 音量调节(递推dp)

原题链接:https://ac.nowcoder.com/acm/problem/19990

思路:

1)很像电梯问题,升或降对应调高或调低,所以内部每次要考虑两个状态。说到内部,如何结合01背包找最大音量呢?

2)我们知道,01背包经典问题是求背包最大容量,其二维dp包括遍历物品和遍历容量两层for循环,最内层更新最优状态.

3)类比经典问题,这道题我们依旧采用两层for,外层遍历n首歌,内层遍历音量,但是每个音量不再是最大价值问题了,变成当前音量能否被演奏(truefalse),结合外层for循环推出的每一个子状态的含义:

dp[i][j] : i首歌能否用j音量演奏

4)最后,稍作判断,得出答案。

 

using namespace std;
const int N = 1010;
int maxL,bgL,n;
int a[60];
int dp[60][N];
// dp(i,j) 第i首歌能否用j音量来演唱  
 
int main()
{
    ios::sync_with_stdio(false);
     
    cin>>n>>bgL>>maxL;
     
    for (int i = 1; i <= n; i++)  {
        cin>>a[i];
    }
     
    dp[0][bgL] = 1; // 初始化
     
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= maxL; j++) {
            if (dp[i-1][j] && j+a[i] <= maxL) { // 能够改变的条件
                dp[i][j+a[i]] = 1;
            }
            if (dp[i-1][j] && j-a[i] >= 0) {
                dp[i][j-a[i]] = 1;
            }
        }
    }
     
    int i;
    for (i = maxL; i >= 0; i--) { // 从后往前判断 
        if (dp[n][i]) {
            cout<<i<<endl;
            break;
        }
    }
    if (i < 0) cout<<-1<<endl;   
     
    return 0;
 }

----------------------------------------------------------   分   割   线 ----------------------------------------------------------

小主如果你有更好的思路和方法,请一定来评论区留言,愿相互学习和进步~

posted @ 2022-12-23 17:05  rainyMo  阅读(55)  评论(0)    收藏  举报