Codeforces Round #260 (Div. 1) A:Boredom(dp)

1.題目鏈接:

https://codeforces.com/problemset/problem/455/A

2.題面:

在這裏插入圖片描述
在這裏插入圖片描述

3.翻譯:

亞歷克斯不喜歡無聊。因此,每當他感到無聊時,他都會提出遊戲。一個漫長的冬天晚上,他想出了一個遊戲,決定玩。
給定一個由n個整數組成的序列。播放器可以執行幾個步驟。在一個步驟中,他可以選擇序列中的一個元素(用ak表示)並將其刪除,因爲所有等於ak + 1和ak-1的元素也必須從序列中刪除。這一步爲玩家帶來了ak分。
亞歷克斯是一位完美主義者,因此他決定獲得儘可能多的積分。救救他

輸入值
第一行包含整數n(1≤n≤105),該整數表示Alex的序列中有多少個數字。
第二行包含n個整數a1,a2,…,an(1≤ai≤105)。

輸出量
打印一個整數-Alex可以賺取的最大積分。

例子
inputCopy
2
1 2
outputCopy
2
inputCopy
3
1 2 3
outputCopy
4
inputCopy
9
1 2 1 3 2 2 2 2 3
outputCopy
10

注意
考慮第三個測試示例。第一步,我們需要選擇等於2的任何元素。在這一步之後,我們的序列看起來像[2,2,2,2]。然後,我們執行4個步驟,在每個步驟上,我們選擇等於2的任何元素。總計,我們獲得10分。

4.思路:

這道題目我們考慮兩種狀態,一是拿了當前元素,得到了當前元素的ak值,而是沒有拿當前元素,則繼承與上一個元素的值
則狀態轉移方程就是

dp[j] =max( dp[ j - 1],dp[ j - 2] +a[ j ])
我們在第i給元素的時候可以選擇拿或者不拿,拿了的話就取到了a【 j 】的ak數再加上前兩個數得到的ak數,以爲當前數字之前的數字已經清0,不拿的話,就取自你前一個數字的數值,以爲你前一個數字拿了的話後面這個值的ak值爲0,就變成了一個簡單的dp問題

5.代碼:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 7;
ll a[MAXN];
ll dp[MAXN];
int main()
{
    ll n, t, maxe = 0;
    cin >> n;
    for (ll i = 1; i <= n; i++)
    {
        cin >> t;
        a[t] += t;//記錄t這個位置可以得到的ak數值
        maxe = max(maxe, t);//得到最大的位置
    }
    dp[0]=0;//0的時候爲0
    dp[1] = a[1];//1的時候就是a[1]的ak數值
    for (ll i = 2; i <= maxe; i++)
    {
        dp[i] = max(dp[i - 1], dp[i - 2] + a[i]);//狀態轉移方程
    }
    cout << dp[maxe] ;//最後輸出到dp[maxe]的值就是最後的答案
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章