• F


    题目大意:从n个数里边选n/2个数,问和最大是多少。

    题解:这是一个比较有意思的DP,定义状态dp[i][1],表示选了第i个数的最优状态,dp[i][0]表示没有选第i个数的最优状态。

    状态是如何转移的呢?

    1  2  3  4  5  6  7....

    假设考虑到第7个数,前7个数我们要选7/2=3个数。

        如果我们选了第7个数那么我们 只需要从前边再选2个数,我们可以从前5个数里边选2个,也可以从前4个数里边选2个,所以dp[i][1]=max({dp[i-2][1],dp[i-2][0],dp[i-3][1],dp[i-3][0]})+arr[i]。  

        如果我们不选第7个数,那就相当于从前6个数选3个喽,直接继承i-1就可以了。dp[i][0]=max(dp[i-1][0],dp[i-1][1])

    假设我们考虑到第6个数,前6个数我们要选3个。

        如果第6个选了,那只能从前4个里边选2个了,不能在往前了,因为3/2=1了。。。所以dp[i][1]=max(dp[i-2][1],dp[i-2][0])+arr[i]。

        如果第6个不选,也就说要从前5个里边选3个了,假设第5个不选,从前4个里边选3个肯定是不满足条件的,所以第5个必须选,然后在加上第四个不选的情况,所以转移方程为dp[i][0]=arr[i-1]+dp[i-2][0]。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=2e5+7;
    ll dp[N][2];
    ll arr[N];
    int main(){
        ll n;
        cin>>n;
        for(ll i=1;i<=n;i++)  cin>>arr[i];
        dp[2][0]=arr[1];
        dp[2][1]=arr[2];
        for(ll i=3;i<=n;i++){
            if(i&1){
                dp[i][1]=max({dp[i-2][1],dp[i-2][0],dp[i-3][1],dp[i-3][0]})+arr[i];
                dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
            }
            else {
                dp[i][1]=max(dp[i-2][1],dp[i-2][0])+arr[i];
                dp[i][0]=arr[i-1]+dp[i-2][0];
            }
        }
        cout<<max(dp[n][0],dp[n][1])<<endl;
        return 0;
    }
  • 相关阅读:
    2016年 CodePen 最热门的前端代码 Top 100
    HttpClientHelper
    .net core mvc 简易登录
    senparc 第三方授权回调,保存授权信息到文件
    盛派微信Sdk .Net Core 初始化注册服务信息
    分享一个gif截图工具
    C# 单例模式
    获取微信AccessToken,保存在内存中,过期后重新获取
    .NET Core WebAPI Swagger使用
    .net Core 读取配置文件参数
  • 原文地址:https://www.cnblogs.com/Accepting/p/12698033.html
Copyright © 2020-2023  润新知