[DP]CF455A Boredom

题面

题目描述

A l e x Alex Alex不喜欢无聊。
所以每当他感到无聊他就会想出一些游戏。一个冬天的晚上他想出了一个游戏并且决定开始玩这个游戏。
给定一个有 n n n个元素的序列 a a a。你可以做若干次操作。在一次操作中我们可以取出一个数 ( ( 假设他为 x ) x) x并删除它,同时删除所有的序列中值为 x + 1 x+1 x+1 x − 1 x-1 x1的数。这一步操作会给玩家加上x分。

输入

第一行一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le10^5) n(1n105),说明这个序列有多少数。 第二行 n n n个整数,分别表示 a 1 a_1 a1, a 2 a_2 a2 … … …… a n a_n an ( 1 ≤ a i ≤ 1 0 5 ) . ( 1\le a_{i}\le 10^{5}). (1ai105).

输出

一个整数,表示玩家最多能获得多少分

思路分析

根据题面可以看到删除所有的序列中值为 x + 1 x+1 x+1 x − 1 x-1 x1的数
也就是说数据的处理与输入的顺序无关

数据处理

for(int i=1;i<=N;i++){
	scanf("%d",&x);
	a[x]++;//运用桶的思想
	Max=max(Max,x);//找到最大的数值
}//数据较小,可以不需要离散

经过处理后,可以直接查询、删除任意所以值为 k k k的数

D P DP DP式推导

这道题其实和这道题很像

Boredom大盗阿福
相同取了 x x x后值为 x + 1 x+1 x+1 x − 1 x-1 x1的会被删除相邻的店不能同时洗劫
不同与序列无关,和每个数的值有关与序列的顺序和值有关

他们的不同之处在数据处理时已经处理好了
所以 D P DP DP式也就可以随之推出:

f[i][0]=max(f[i-1][1],i>=2?f[i-2][1]:0);//当前数不取可以由上一个取或上上个取得来
f[i][1]=f[i-1][0]+a[i]*i;//当前数取便是由上个数不取加上当前数取的得分

完整代码

#include<bits/stdc++.h>
#define Maxn 100039
using namespace std;
int max(int a,int b){return a>b?a:b;}
int f[Maxn][2],N;
int a[Maxn],Max;
int main(){
	scanf("%d",&N);
	int x;
	for(int i=1;i<=N;i++){
		scanf("%d",&x);
		a[x]++;
		Max=max(Max,x);
	}
	for(int i=1;i<=Max;i++){
		f[i][0]=max(f[i-1][1],i>=2?f[i-2][1]:0);
		f[i][1]=f[i-1][0]+a[i]*i;
	}
	printf("%d",max(f[Max][1],f[Max][0]));
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值