题目描述:
YJQ 上完第10周的程序设计思维与实践后,想到一个绝妙的主意,他对拿数问题做了一点小修改,使得这道题变成了 拿数问题 II。
给一个序列,里边有 n 个数,每一步能拿走一个数,比如拿第 i 个数, Ai = x,得到相应的分数 x,但拿掉这个 Ai 后,x+1 和 x-1 (如果有 Aj = x+1 或 Aj = x-1 存在) 就会变得不可拿(但是有 Aj = x 的话可以继续拿这个 x)。求最大分数。
思路:
- 因为要求拿到的数总和最大,所以可以认为所有的数都是正整数,因为即使有负数,也不可能去拿负数,而且如果序列中有多个相同的X,则如果拿了其中一个X,则其他X一定也要拿
- 把这个问题转化为普通的拿数问题,可以认为有10^5个数,从1-10^5,如果i在序列中,则其表示的数是i*fre(fre是i在序列中出现的次数);如果i不在序列中,则其表示的数就是0
代码:
#include <cstdio> #include <iostream> using namespace std; typedef long long ll; const int MAXN=1e5+5; ll cnt[MAXN]; ll dp[MAXN]; int main() { int N; cin>>N; for(int i=1;i<=N;i++) { int x; scanf("%d",&x); cnt[x]+=x; } dp[1]=cnt[1]; for(int i=2;i<MAXN;i++) { dp[i]=max(dp[i-1],dp[i-2]+cnt[i]); } cout<<dp[MAXN-1]<<endl; return 0; }