zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    POJ1985 树的直径(BFS
    POJ2186 强连通分量+缩点
    AIM Tech Round 5C. Rectangles 思维
    POJ2553 汇点个数(强连通分量
    hdu6370 并查集+dfs
    UVALive 7037:The Problem Needs 3D Arrays(最大密度子图)
    POJ 3155:Hard Life(最大密度子图)
    HDU 5527:Too Rich(DFS+贪心)***
    HDU 5534:Partial Tree(完全背包)***
    Wannafly挑战赛1:Treepath(DFS统计)
  • 原文地址:https://www.cnblogs.com/Accepting/p/12698033.html
Copyright © 2011-2022 走看看