CF 445A 简单DP

今天早上找一道题的bug,还是找不出来,下午刷了几道水题,晚上准备回家的事,

然后本来想打CF的,一看,数学场,不打了。

这道题的题意:

给出一个序列,每次你可以从这个序列里面选择一个数ak,删除,然后你的得分+ak,

代价是序列里面值为ak+1,ak-1的元素都删除

问:你能得到的最大得分是多少

思路:

你若删除了一个值为a的数,你的得分就是a*序列里面a的个数

因为a+1和a-1都被删除了,则其余的a不会被a+1,a-1这种情况删除了,你一定可以得到所有a的分数

所以这道题就是:在序列里面选择一些数值,你的得分+数值*该值出现的个数,并且,

数值+1和数值-1的数你就不能选了。

num[i]表示值i出现的次数。

_max表示出现的最大的值

dp[i][0]:表示从值1选择到i,如果不选择值i,可以得到的最大分数

dp[i][1]:表示从值1选择到值i,如果选择了值i,可以得到的最大分数。

注意:

1.这道题最后的结果要long long

2.小心中间过程溢出,我就是这个贡献了2个wa

3.CF的long long 要用cout输出

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 #define LL long long
 7 const int maxn=1e5+10;
 8 
 9 inline LL max(LL x,LL y)
10 {
11     return x>y?x:y;
12 }
13 
14 int a[maxn];
15 LL dp[maxn][2];
16 
17 int main()
18 {
19     int n;
20     scanf("%d",&n);
21     int _max=-1;
22     memset(a,0,sizeof a);
23     for(int i=1;i<=n;i++)
24     {
25         int u;
26         scanf("%d",&u);
27         a[u]++;
28         if(u>_max)
29             _max=u;
30     }
31 
32     memset(dp,0,sizeof dp);
33     for(int i=1;i<=_max;i++)
34     {
35         dp[i][1]=dp[i-1][0]+(LL)a[i]*i;
36         dp[i][0]=max(dp[i-1][1],dp[i-1][0]);
37     }
38 
39     cout<<max(dp[_max][1],dp[_max][0])<<endl;
40 
41     return 0;
42 }
View Code
原文地址:https://www.cnblogs.com/-maybe/p/4719861.html