问题描述
小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是K的两名用户匹配在一起。如果两人分差小于或大于K,系统都不会将他们匹配。
现在小明知道这个网站总共有N名用户,以及他们的积分分别是A1, A2, … AN。
小明想了解最多可能有多少名用户同时在线寻找对手,但是系统却一场对局都匹配不起来(任意两名用户积分差不等于K)?
输入格式
第一行包含两个个整数N和K。
第二行包含N个整数A1, A2, … AN。
对于30%的数据,1 <= N <= 10
对于100%的数据,1 <= N <= 100000, 0 <= Ai <= 100000, 0 <= K <= 100000
输出格式
一个整数,代表答案。
样例输入
10 0
1 4 2 8 5 7 1 4 2 8
样例输出
6
思路分析
题目要求任意两名用户的积分差不等于k
,那我们就把积分差为k
的用户放在一个集合里判断,这样就把所有用户分为了k
个集合,这样任意两个不同的集合中的任意两个元素的积分差都不等于k
,所以题目也相对的变成了求每一个集合中积分差不等于k
的最大人数,动态规划,我们假设前i-1
个状态对应的最大人数已经求出来了,所以第i
个状态就是max(dp[i-1],dp[i-2]+a[i])
,即不取第i
个和取第i
个的最大值,当i==0||i==1
时,特判一下,还有特判k==0
的情况就AC了。
在进行dp
的的时候,最好另开一个数组开存每一个集合,这样dp
写起来很舒服。
AC代码
#include<iostream>
using namespace std;
int book[100005],a[100005],dp[100005];
int main()
{
int i,j,n,k,t,x=0,ans=0;
cin>>n>>k;
for (i=0;i<n;i++)
{
cin>>t;
book[t]++;
}
if (k==0)
{
for (i=0;i<100005;i++)
{
if (book[i]!=0)
ans++;
}
cout<<ans;
return 0;
}
else
{
for (i=0;i<k;i++)
{
x=0;
for (j=i;j<100005;j+=k)
a[x++]=book[j];
for (j=0;j<x;j++)
{
if (j==0)
dp[0]=a[0];
else if (j==1)
dp[1]=max(a[1],dp[0]);
else
dp[j]=max(dp[j-1],dp[j-2]+a[j]);
}
ans+=dp[x-1];
}
}
cout<<ans;
}