题目描述
“分享狼血,与子同胞”
“漫步深渊,心怀正义”
“侍奉光明,斩杀黑暗”
“因剑而生,因剑而死”
“深渊无尽,我等将不娶妻,不生子,只求一世荣耀”
“光阴有时,我等必守此誓,献此生,但愿诸界太平”
无火的余烬,你追随者古老的誓言来到了法兰要塞,为了通过烽火试炼,你必须收集足够多的灵魂。
已知要塞里有n个怪物,不同的怪物有着不同的血量a。每次,你可以选择消灭一只怪物,同时所有血量为a+1和a-1的怪物也会死去。同时你可以获得a个灵魂。
输入
第一行输入一个整数n(1<=n<=105)
第二行输入n个整数a1,a2,…an(1<=ai<=105)
输出
请输出无火的余烬可以获得的最大灵魂数量
样例输入
9
1 2 1 3 2 2 2 2 3
样例输出
10
提示
对于样例,第一次可以选择血量为2的怪物将其消灭。在这之后,我们的序列是这样的[2,2,2,2],然后可以再进行四次,每次选择一个血量为2的怪物消灭。最终我们能够获得10个灵魂。
思路:
动态规划思想。
可以想成如果杀血量为1的怪物,则不能杀血量为2的怪物,如果不杀血量为1的怪物,则血量为2的怪物,可以杀也可以不杀。
dp[i][0]是不杀该血量怪物的最大值,dp[i][1]是杀该血量怪物的最大值,如果杀了dp的值是,第i-1血量没杀的值加上i血量杀的值。如果不杀,dp的值第i-1血量没杀的值和i-1血量杀了的最大值。
#include <bits/stdc++.h>
using namespace std;
long long arr[100005];
long long dp[100005][2];
int main(){
int n, a;
cin>>n;
memset(arr, 0, sizeof(arr));
memset(dp, 0, sizeof(dp));
// arr[n] 血量为n的灵魂数量
for(int i = 0; i < n; i++){
scanf("%d", &a);
arr[a] = arr[a] + a;
}
long long ans = 0;
for(int i = 1; i < 100005; i++){
dp[i][0] = max(dp[i-1][0], dp[i-1][1]);
dp[i][1] = dp[i-1][0] + arr[i];
ans = max(ans, dp[i][0]);
ans = max(ans, dp[i][1]);
}
cout << ans;
}