import java.util.*;
/**
* NC300 删除相邻数字的最大分数
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 相似 => NC176 打家劫舍(一)
* @param a int整型ArrayList
* @return int整型
*/
public int boredom (ArrayList<Integer> a) {
// return solution1(a);
return solution2(a);
// return solution3(a);
}
/**
* 动态规划
*
* dp[i][0]表示第i种数字不选择时能得到的最多分数
* dp[i][1]表示第i种数字要选择时能得到的最多分数
*
* dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1])
* { dp[i-1][0] + map.get(curr) , pre+1 == curr
* dp[i][1] = {
* { Math.max(dp[i-1][0], dp[i-1][1]) + map.get(curr) , pre+1 != curr
*
* @param a
* @return
*/
private int solution1(ArrayList<Integer> a){
// 保证有序
TreeSet<Integer> set = new TreeSet<Integer>();
// 存储分数
HashMap<Integer, Integer> map = new HashMap<>();
for(int num: a){
set.add(num);
map.put(num, map.getOrDefault(num,0)+num);
}
int len = set.size();
int[][] dp = new int[len+1][2];
// 前面数字
int pre=-1;
// 当前数字
int curr;
for(int i=1; i<=len; i++){
curr = set.pollFirst();
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1]);
if(pre+1 == curr){
dp[i][1] = dp[i-1][0] + map.get(curr);
}else{
dp[i][1] = Math.max(dp[i-1][0], dp[i-1][1]) + map.get(curr);
}
pre = curr;
}
return Math.max(dp[len][0], dp[len][1]);
}
/**
* 动态规划
*
* dp[i]表示到达数字i时能得到的最多分数
*
* dp[i] = Math.max(dp[i-1], dp[i]+dp[i-2])
*
* @param a
* @return
*/
private int solution2(ArrayList<Integer> a){
int max = 0;
for(int num: a){
max = Math.max(max, num);
}
// init
int[] dp = new int[max+1];
for(int num: a){
dp[num] += num;
}
for(int i=2; i<=max; i++){
dp[i] = Math.max(dp[i-1], dp[i]+dp[i-2]);
}
return dp[max];
}
/**
* 动态规划
*
* dp[i]表示到达数字i时能得到的最多分数
*
* dp[i] = Math.max(dp[i-1], dp[i]+dp[i-2])
*
* @param a
* @return
*/
private int solution3(ArrayList<Integer> a){
int max = 10000;
// init
int[] dp = new int[max+1];
for(int num: a){
dp[num] += num;
}
for(int i=2; i<=max; i++){
dp[i] = Math.max(dp[i-1], dp[i]+dp[i-2]);
}
return dp[max];
}
}