两个选与不选的dp
例一:
链接:https://ac.nowcoder.com/acm/contest/8755/F
来源:牛客网
露米娅作为宵暗的妖怪,非常喜欢吞噬黑暗。
这天,她来到了一条路上,准备吞噬这条路上的黑暗。
这条道路一共被分为
部分,每个部分上的黑暗数量为
。
露米娅每次可以任取 连续的 未被吞噬过的 三部分,将其中的黑暗全部吞噬,并获得中间部分的饱食度。
露米娅想知道,自己能获得的饱食度最大值是多少?
输入描述:
第一行一个正整数
,代表道路被分的份数。
第二行有
个正整数
,代表每一部分黑暗数量。
数据范围:
输出描述:
一个正整数,代表最终饱食度的最大值。
示例2
说明
选择[1,7,2]这一段即可。饱食度为7。
值得注意的是,若取两段进行吞噬,反而最多只能获得6的饱食度,并不是最大的。
这个题就是dp[i][1]代表的是前i个并且第i个取的时候最大值
转移方程为dp[i][1]=dp[i-2][0]+a[i];
比如说2 4 1 4 2 1,就是说如果选第二个2的话那么那个1一定是不能选的,如果选1的话会有重合的
dp[i][0]代表的是前i个并且第i个不取的时候最大
dp[i][0]=max(dp[i-1][1],dp[i-1][0]);
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e6+100; ll a[maxn]; ll dp[maxn][2]; int n; int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=2;i<=n-1;i++){ dp[i][1]=dp[i-2][0]+a[i]; dp[i][0]=max(dp[i-1][1],dp[i-1][0]); } printf("%lld\n",max(dp[n-1][1],dp[n-1][0])); }
思路:dp[i]代表以第i项为结尾的最大值是多少,从第四项开始计算,小A可以吃当前这个黑暗数量dp[i - 3] + a[i],也可以不吃dp[i - 1]
dp[i] = max(dp[i - 3] + a[i],dp[i - 1]);
思路:dp[i]代表以第i项为结尾的最大值是多少,从第四项开始计算,小A可以吃当前这个黑暗数量dp[i - 3] + a[i],也可以不吃dp[i - 1] dp[i] = max(dp[i - 3] + a[i],dp[i - 1]); #include <iostream> #include <queue> using namespace std; typedef long long LL; const int N = 1e5 + 10; LL dp[N]; LL a[N]; int main() { int n; cin >> n; for(int i = 1;i <= n;i ++) cin >> a[i]; dp[2] = a[2]; dp[3] = max(a[3],a[2]); LL res = a[3]; for(int i = 4;i < n;i ++) { dp[i] = max(dp[i - 3] + a[i],dp[i - 1]); res = max(res,dp[i]); } if(n == 3){ res = dp[2]; } cout << res << endl; return 0; }