问题描述(题目链接:
对局匹配)
小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是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; }