Boredom(簡單dp)
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)