week10 作業C 拿數問題II

2021-10-05 09:12:09 字數 1461 閱讀 7445

給 n 個數,每一步能拿走乙個數,比如拿第 i 個數, ai = x,得到相應的分數 x,但拿掉這個 ai 後,x+1 和 x-1 (如果有 aj = x+1 或 aj = x-1 存在) 就會變得不可拿(但是有 aj = x 的話可以繼續拿這個 x)。求最大分數。

本題和課上講的有些許不一樣,但是核心是一樣,需要你自己思考。

input

第一行包含乙個整數 n (1 ≤ n ≤ 105),表示數字裡的元素的個數

第二行包含n個整數a1, a2, …, an (1 ≤ ai ≤ 105)

output

輸出乙個整數:n你能得到最大分值。

example

input

21 2

output

2input

31 2 3

output

4input

91 2 1 3 2 2 2 2 3

output

10

我的思路:

這道題與課堂上講的不同,課堂是位置相鄰的不能加,而這道題是在分數大小上相鄰的不能加而相同分數可以加。我們可以根據這個特點,對於問題進行乙個轉化,可以記錄

每個數字的出現次數,從而形成乙個陣列sum,索引值為這個數字,裡面的數即為出現的次數,這樣就把問題又轉變成了相鄰不能加的問題。於是,可以推出從當前位置到最前方的最大分數dp[i] = max(dp[i-1],dp[i-2]+i*sum[i])。這裡可以先輸入的時候,記錄所有數字的最小值minx和最大值maxx,然後最後做dp遞推時,直接從minx到maxx計算即可。

我的總結:

最開始,我的計算方法是對於這些數字進行公升序排序,然後遍歷找之前比自己的小2及以上或等於自己的數字加上他們的dp作為當前數的dp,最後找到最大的dp即可。然而,這種方法較為樸素,時間複雜度太高,會tle,所以最後選擇上文所說的方法。

我的**:

#include

#include

using

namespace std;

long

long a[

100010

],dp[

100010

],sum[

100010

],n,minx=

100010

,maxx=0;

intmain()

for(

int i=minx;i<=maxx;i++

) cout

}

Week10 作業 C 拿數問題 II

一 題目描述 題面 給 n 個數,每一步能拿走乙個數,比如拿第 i 個數,ai x,得到相應的分數 x,但拿掉這個 ai 後,x 1 和 x 1 如果有 aj x 1 或 aj x 1 存在 就會變得不可拿 但是有 aj x 的話可以繼續拿這個 x 求最大分數。本題和課上講的有些許不一樣,但是核心是...

Week10 作業C 拿數問題 II

yjq 上完第10周的程式設計思維與實踐後,想到乙個絕妙的主意,他對拿數問題做了一點小修改,使得這道題變成了 拿數問題 ii。給乙個序列,裡邊有 n 個數,每一步能拿走乙個數,比如拿第 i 個數,ai x,得到相應的分數 x,但拿掉這個 ai 後,x 1 和 x 1 如果有 aj x 1 或 aj ...

Week 10 拿數問題II

yjq 上完第10周的程式設計思維與實踐後,想到乙個絕妙的主意,他對拿數問題做了一點小修改,使得這道題變成了 拿數問題 ii。給乙個序列,裡邊有 n 個數,每一步能拿走乙個數,比如拿第 i 個數,ai x,得到相應的分數 x,但拿掉這個 ai 後,x 1 和 x 1 如果有 aj x 1 或 aj ...