题目大意:输入一个序列的整数,进行删除操作, 如果删除 x 那么队列中所有的 x+1 和 x-1 (注意时值,不是下标,一开始理解错题意了,坑死....) 就要删除.
同时获得 x的个数乘以x的分数, 求出最高得分。 简单的01背包问题, 就是删除还是不删除当前数字,比较往前数两个加上但前的值 与前一个进行比较就好。
一开始的AC 代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstring>
using namespace std;
long long cnt[100050];
long long dp[100050];
int main()
{
int n;
int maxa;
memset(dp, 0, sizeof(dp));
scanf("%d", &n);
int a;
for(int i=0; i<n; i++)
{
scanf("%d", &a);
if(a > maxa) maxa = a;
cnt[a] ++;
}
long long ans = 0;
dp[1] = cnt[1];
for(int i=1; i<= maxa; i++)
{
if(i-2 >= 0) dp[i] = max(dp[i-1], dp[i-2]+ i*cnt[i]);
if(dp[i] > ans) ans = dp[i];
}
cout << ans << endl;
return 0;
}
后来改良版,优化了空间(减少了一个数组):
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstring>
using namespace std;
long long cnt[100050];
int main()
{
int n;
int maxa = 0;
scanf("%d", &n);
int a;
for(int i=0; i<n; i++)
{
scanf("%d", &a);
if(a > maxa) maxa = a;
cnt[a]++;
}
long long ans = cnt[1];
long long x1 = 0;
long long x2 = 0;
long long t;
for(int i=1; i<= maxa; i++)
{
t = x2;
x2 = max(x2, x1 + i*cnt[i]);
if(x2 > ans) ans = x2;
x1 = t;
}
cout << ans << endl;
return 0;
}