Codeforces Round #260 (Div. 1) A - Boredom DP
题意:
给你n个数,你每次可以选择删除去一个数x,但是等于x+1和等于x-1的数都得删去
你每一次操作可以得x分
思路一:
dp[i]表示到i后能够得到的最大分数
dp[i]=max(dp[i-1],dp[i-2]+a[i]*i;
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5+10; 5 inline ll read(){ 6 ll x=0,f=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 9 return x*f; 10 } 11 12 ll a[maxn],dp[maxn]; 13 14 int main(){ 15 int n; 16 cin >> n; 17 for(int i=1; i<=n; i++){ 18 ll x; cin >> x; 19 a[x]++; 20 } 21 22 memset(dp,0,sizeof(dp)); 23 24 for(int i=1; i<maxn; i++){ 25 dp[i] = max(dp[i-1],dp[i-2]+a[i]*i); 26 } 27 28 cout << dp[maxn-1] << endl; 29 30 return 0; 31 }
思路二:
用计数排序统计数字的个数
dp[ i ][ 0 ]表示不删除 i ,dp[ i ][ 1 ]表示删除 i
dp[ i ][ 0 ] = max( dp[ i-1 ][ 1 ] , dp[ i-1 ][ 0 ] );
dp[ i ][ 1 ] = dp[ i-1 ][ 0 ] + i * a[ i ];
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5+10; 5 const int INF = 0x3f3f3f3f; 6 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 7 inline ll read(){ 8 ll x=0,f=1;char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 11 return x*f; 12 } 13 ////////////////////////////////////////////////////////////////////////// 14 15 ll a[maxn],dp[maxn][2]; 16 int mx=-1; 17 18 int main(){ 19 int n; n = read(); 20 for(int i=1; i<=n; i++){ 21 int x; x = read(); 22 a[x]++; 23 mx = max(x,mx); 24 } 25 26 for(int i=1; i<=mx; i++){ 27 dp[i][1] = dp[i-1][0]+a[i]*i; // dp[i][1] 表示这个数删 28 dp[i][0] = max(dp[i-1][1],dp[i-1][0]); // dp[i][0] 表示这个数不删 29 } 30 31 cout << max(dp[mx][0],dp[mx][1]) << endl; 32 return 0; 33 }
滚动优化:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5+10; 5 const int INF = 0x3f3f3f3f; 6 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 7 inline ll read(){ 8 ll x=0,f=1;char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 11 return x*f; 12 } 13 ////////////////////////////////////////////////////////////////////////// 14 15 ll a[maxn],dp[2][2]; 16 int mx=-1; 17 18 int main(){ 19 int n; n = read(); 20 for(int i=1; i<=n; i++){ 21 int x; x = read(); 22 a[x]++; 23 mx = max(x,mx); 24 } 25 26 int now = 0, pre = 1;; 27 for(int i=1; i<=mx; i++){ 28 29 dp[now][1] = dp[pre][0]+a[i]*i; // dp[now][1] 表示这个数删 30 dp[now][0] = max(dp[pre][1],dp[pre][0]); // dp[now][0] 表示这个数不删 31 swap(now, pre); 32 } 33 34 dp[now][0] = max(dp[now][0],dp[pre][0]); 35 dp[now][1] = max(dp[now][1],dp[pre][1]); 36 37 ll ans = max(dp[now][0],dp[now][1]); 38 cout << ans << endl; 39 40 return 0; 41 }