问题描述(题目链接:
对局匹配)
小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是K的两名用户匹配在一起。如果两人分差小于或大于K,系统都不会将他们匹配。
现在小明知道这个网站总共有N名用户,以及他们的积分分别是A1, A2, ... AN。
小明想了解最多可能有多少名用户同时在线寻找对手,但是系统却一场对局都匹配不起来(任意两名用户积分差不等于K)?
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是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
第二行包含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
1 4 2 8 5 7 1 4 2 8
样例输出
6
思路 (参考博客:https://blog.csdn.net/flyawayl/article/details/79068946)
如果把n个元素按照将分数相差为k的用户分成一组,例如第一组就是{0,k,2k,3k...},第二组就是{1,k+1,2k+1...},等等。这样分组的话,每个分组的用户是不可能和其他分组的用户匹配成功的,因为分差不可能为k。
。
状态转移方程如下:
dp[i] = max( dp[i-1] , dp[i-2]+cnt[score] )
需要注意的是,k=0要特殊处理。
这个题最主要的是解决分组的问题,解决分组之后就能想到用DP的思想求得最大值。
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
const int maxn=1e5+10;
int a[maxn],dp[maxn],cnt[maxn];
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
memset(a,0,sizeof(a));
int x;
for(int i=0; i<n; ++i)
{
scanf("%d",&x);
a[x]++;
}
int ans=0,id;
if(k==0)
{
for(int i=0; i<maxn; ++i)
if(a[i]) ++ans;
}
else
{
for(int i=0; i<k; ++i)
{
id=0;
for(int j=i; j<maxn; j+=k)
cnt[id++]=a[j];
dp[0]=cnt[0];
for(int j=0; j<id; ++j)
{
if(j==1) dp[j]=max(dp[j-1],cnt[j]);
else
{
dp[j]=max(dp[j-1],dp[j-2]+cnt[j]);
}
}
ans+=dp[id-1];
}
}
printf("%d\n",ans);
}
return 0;
}