两个选与不选的dp

例一:

链接:https://ac.nowcoder.com/acm/contest/8755/F
来源:牛客网

露米娅作为宵暗的妖怪,非常喜欢吞噬黑暗。
这天,她来到了一条路上,准备吞噬这条路上的黑暗。
这条道路一共被分为部分,每个部分上的黑暗数量为
露米娅每次可以任取 连续的 未被吞噬过的 三部分,将其中的黑暗全部吞噬,并获得中间部分的饱食度。
露米娅想知道,自己能获得的饱食度最大值是多少?

输入描述:

第一行一个正整数

,代表道路被分的份数。 
第二行有

个正整数

,代表每一部分黑暗数量。 
数据范围:

输出描述:

一个正整数,代表最终饱食度的最大值。
示例1

输入

复制
7
2 4 1 4 2 1 8

输出

复制
6

说明

选择[2,4,1]和[4,2,1]这两段即可。饱食度为4+2=6。
示例2

输入

复制
7
2 4 1 7 2 1 8

输出

复制
7

说明

选择[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;
}

 

posted @ 2020-11-23 00:07  哎呦哎(iui)  阅读(161)  评论(0编辑  收藏  举报