Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long winter evening he came up with a game and decided to play it.
Given a sequence a consisting of n integers. The player can make several steps. In a single step he can choose an element of the sequence (let's denote it ak) and delete it, at that all elements equal to ak + 1 and ak - 1 also must be deleted from the sequence. That step brings ak points to the player.
Alex is a perfectionist, so he decided to get as many points as possible. Help him.
The first line contains integer n (1 ≤ n ≤ 105) that shows how many numbers are in Alex's sequence.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 105).
Print a single integer — the maximum number of points that Alex can earn.
2 1 2
2
3 1 2 3
4
9 1 2 1 3 2 2 2 2 3
10
Consider the third test example. At first step we need to choose any element equal to 2. After that step our sequence looks like this [2, 2, 2, 2]. Then we do 4 steps, on each step we choose any element equals to 2. In total we earn 10 points.
题目大意:
给出N个数字,范围在1~10^5之内,现在做一个游戏,每次抽出一个数字a,将a删掉并计入分数,同时删掉所有等于a-1和a+1的数字。现在求分数最大。
解法:
很简单的一道DP,首先统计每个数字总共有多少个。
由于抽a会将a-1和a+1都删掉,为了避免后效性,我们将统一方向,如若选择a,则a-1均被删除,a+1不管,因为我们是从1~maxn。我们设f[i]为选择到数字i的时候,可以获得的最大分数,这里有两种选择,一种是该层数字不选择,直接选择前一个数字,那么该层数字就会被删除即不计入分数,如若选择前2个数字,则可以选择该层数字。
状态转移方程:f[i] = max(f[i-1], f[i-2]+a[i]*i);
代码:
#include <cstdio>
#include <algorithm>
#define N_max 123456
#define LL long long
using namespace std;
int n;
LL a[N_max], f[N_max], ans, tmp;
void init() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%I64d", &tmp);
a[tmp]++;
}
}
void solve() {
f[1] = a[1];
ans = f[1];
for (int i = 2; i < N_max; i++) {
f[i] = max(f[i-1], f[i-2]+a[i]*i);
ans = max(f[i], ans);
}
printf("%I64d\n", ans);
}
int main() {
init();
solve();
}