牛客-[HAOI2012]音量调节音量调节——01背包问题或者回溯记忆化

Posted C+++++++++++++++++++

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客-[HAOI2012]音量调节音量调节——01背包问题或者回溯记忆化相关的知识,希望对你有一定的参考价值。

题目

题目链接

题目解析

首先根据题目的意思,我们很快可以建立起一个逻辑:

给一组数据添 + 或者 - 号,然后要让它们得到的最终结果尽量的大!

但注意啊,中间不能存在吉他低于0或者高于maxLevel的情况!否则吉他可能报废,我觉得差不多应该是这么个意思。

故很快啊,写个回溯,然后很快啊,就会超时。。。这个时候再对回溯过程加一个记忆化即可,实际上有用的可能就是中间出现0的时候可以优化它不继续重复计算了。其他情况这个记忆化等于没用,但正好就是这个对 +-0 情况的记忆化让这道题就能过了!

以下为记忆化的解题代码

#include<bits/stdc++.h>
using namespace std;

const int maxn = 105;
int n, beginLevel, maxLevel, ans = -maxn;
int a[maxn];

int dp[maxn][1005];//TODO 这个记忆化主要针对重复性动作,比如+0或-0是一样的
bool solve(int curLevel, int t) //curLevel表示当前音量,t表示第t首曲子
    if (curLevel > maxLevel || curLevel < 0) 
        return false;//TODO 不能在选择途中出现吉他低于0或者高于maxLevel的情况!
                     // 否则吉他可能报废,差不多应该是这么个意思
    
    if(dp[t][curLevel]!=-1)return dp[t][curLevel];
        //已经是最后一首曲子,更新最大值ans
    if (t == n + 1) 
        ans = max(ans, curLevel);
        return true;
    
    bool plus = solve(curLevel + a[t], t + 1);
    bool minus = solve(curLevel - a[t], t + 1);
        //若尝试两种情况都失败了
    if (!plus && !minus) 
        return dp[t][curLevel] = false;
    
    return dp[t][curLevel] = true;


int main() 
    ios::sync_with_stdio(false);
    cin>>n>>beginLevel>>maxLevel;
    for (int i = 1; i <= n; i++) 
        cin>>a[i];
    
    memset(dp,0xff,sizeof(dp));
    if (solve(beginLevel, 1)) 
        cout<<ans<<'\\n';
     else 
        cout<<-1;
    

    return 0;

从最终的情况来说,这题考察的实际上应该是背包问题,是01背包问题,只不过这个背包可以加也可以减去这个值。

对于背包问题来说,也就在于物品的种类以及取与不取而已。

这部分直接看解题代码即可。

解题代码

#include <bits/stdc++.h>
using namespace std;
int nums[55];
bool dp[55][1005];//TODO 如果dp[i][j]为true表示j在前i个物品的加持下能够拼出
int n;
int ret = -1;
int mx,mn;

int main () 
    ios::sync_with_stdio(false);
    cin>>n>>mn>>mx;
    for (int i = 1; i <= n; ++i) 
        cin>>nums[i];
    
    //TODO 开始01背包更新
    dp[0][mn] = 1;//TODO 当不选择任何物品时,可以得到最低音
    for(int i=1;i<=n;i++)
        for(int j=0;j<=mx;j++)
            if(j>=nums[i])//TODO 背包取加法
                dp[i][j] |= dp[i-1][j-nums[i]];
            if(j+nums[i]<=mx)//TODO 背包取减法
                dp[i][j] |= dp[i-1][j+nums[i]];
        
    
    //TODO 搜索能够取到的的最大值
    for(int p=mx;p>=0;p--)
        if(dp[n][p])
        
            ret = p;
            break;
        
    cout<<ret;
    return 0;

以上是关于牛客-[HAOI2012]音量调节音量调节——01背包问题或者回溯记忆化的主要内容,如果未能解决你的问题,请参考以下文章

P1877 [HAOI2012]音量调节

P1877 [HAOI2012]音量调节

洛谷 P1877 [HAOI2012]音量调节

Bzoj 2748: [HAOI2012]音量调节 动态规划

洛谷 P1877 [HAOI2012]音量调节

[HAOI2012]音量调节