1. 程式人生 > >Boredom(簡單dp)

Boredom(簡單dp)

pan mem hid ive open mar rom prim sam

Description

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.

Input

The first line contains integer n (1 ≤ n ≤ 10^5) that shows how many numbers are in Alex‘s sequence.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 10^5)

Output

Print a single integer — the maximum number of points that Alex can earn.

Sample Input

9
1 2 1 3 2 2 2 2 3

Sample Output10


分析:很容易觀察到數據的先後是不影響值的大小的,所以我們不妨先用一個桶排序。
接下來再看這個問題:對於每個數字我們有兩種選擇:選還是不選,而且前面數字的選對後面(差大於1)的數字是沒有影響的,即無後效性,考慮dp。
假如我們用數組dp[i]保存數據i的狀態,考慮從左往右進行分析(類似背包問題,每個物品選還是不選)

對第i個物品,假如我們選這個物品,那麽dp[i]=dp[i-2]+a[i]*i(之前的分數加上這次的分數)
如果我們不選這個物品,那麽dp[i]=dp[i-1](因為沒有選擇所以分數不變)
那麽狀態轉移方程就是dp[i]=max(dp[i-1],dp[i-2]+a[i]*i)

技術分享圖片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 const int MAXN=1e5+5;
 8 ll a[MAXN];
 9 ll dp[MAXN];
10 ll n,x,maxn;
11 ll ans;
12 
13 int main()
14 {
15     while(scanf("%lld",&n)!=EOF)
16     {
17         maxn=0; ans=0;
18         memset(a,0,sizeof(a));
19         for(int i=0;i<n;i++)
20         {
21             scanf("%lld",&x);
22             if(maxn<x) maxn=x;
23             a[x]++;
24         }
25         memset(dp,0,sizeof(dp));
26         dp[1]=a[1];
27         for(ll i=2;i<=maxn;i++)
28         {
29             dp[i]=max(dp[i-1],dp[i-2]+a[i]*i);
30             //ans=max(ans,dp[i]);
31         }
32         printf("%lld\n",dp[maxn]);
33     }
34     return 0;
35 }
AC Code

前面wa了好多次,記錄一下錯因:

 1.忘記開long long (有可能10^5*10^5)

 2.用ans保存結果忘記分析循環無法執行的情況(自閉)

技術分享圖片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 const int MAXN=1e5+5;
 8 ll a[MAXN];
 9 ll dp[MAXN];
10 ll n,x,maxn;
11 ll ans;
12 
13 int main()
14 {
15     while(scanf("%lld",&n)!=EOF)
16     {
17         maxn=0; ans=0;
18         memset(a,0,sizeof(a));
19         for(int i=0;i<n;i++)
20         {
21             scanf("%lld",&x);
22             if(maxn<x) maxn=x;
23             a[x]++;
24         }
25         memset(dp,0,sizeof(dp));
26         dp[1]=a[1];
27         for(ll i=2;i<=maxn;i++)
28         {
29             dp[i]=max(dp[i-1],dp[i-2]+a[i]*i);
30             ans=max(ans,dp[i]);
31         }
32         printf("%lld\n",ans);
33     }
34     return 0;
35 }
Wa Code

 

Boredom(簡單dp)