2021.02.25对局匹配
题目描述
有一匹配系统,只匹配分数刚好相差k的选手,现在输入n位选手和分差k,求最多有多少名选手同时在线,仍无法匹配一组对局(任意两名选手积分差不为k)。
输入格式
第一行包含两个个整数N和K。
第二行包含N个整数A1, A2, … AN。
样例输入
10 0
1 4 2 8 5 7 1 4 2 8
样例输出
6
数据规模和约定
对于100%的数据,1 <= N <= 100000, 0 <= Ai <= 100000, 0 <= K <= 100000
思路
错误思路
排序后直接动态规划dp[i]表示前i个分数的ans(会出现问题)
正确思路
分组后进行动态规划
- 分成起点不同,但是间隔相同的k组。(起点是0,1,…,k-1)
- 不同组别之间是不可能相差k分的。如果大小最贴近,最大分差将<k,否则最小分差>k.
代码
class Solution{
int len = 100010;
int n,k;
int[] cnt = new int[100010];
int[] arr = new int[100010];
int[] dp = new int[100010];
void test() {
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
k = cin.nextInt();
for(int i = 0; i < n; i++) {
int num = cin.nextInt();
cnt[num]++;
}
if(k == 0) {
int ans = 0;
for(int i = 0; i < n; i++)
if(cnt[i]!=0) ans++;
System.out.println(ans);
return;
}
//k != 0
int ans = 0;
for(int i = 0; i < k; i++) { //共分成k组,但是起点不一样
int x = 0; //表示该组中元素的个数
//起点是0,1,2,...,k-1
for(int j = i; j < len; j+=k)
arr[x++] = cnt[j];
for(int j = 0; j < x; j++) {
if(j == 0) {
dp[0] = arr[0];
} else if(j == 1) {
dp[1] = Math.max(arr[0],arr[1]);
} else {
dp[j] = Math.max(dp[j-1], dp[j-2]+arr[j]);
}
}
//由于任两个不同组的分数都无法匹配,所以ans是各组动态规划结果之和
ans+=dp[x-1];
}
System.out.println(ans);
}
}