牛客-[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背包问题或者回溯记忆化的主要内容,如果未能解决你的问题,请参考以下文章