蓝桥杯 试题 历届试题 对局匹配 DP解决
问题描述
小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是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的分为一组,这样每组之间都不会匹配,再从每组中选择一个最佳方案,把最优方案相加即可
得到一个最优解。但如何在并查集同一组中选择最优方案又成了问题。最后看到别的朋友的思路才知道用DP解决。我的代码主要和一位朋友的相似,所以附上链接https://blog.csdn.net/Helloirbd/article/details/88070674 我的代码只是用了《挑战程序设计竞赛》的风格重复了一遍。
可以用A数组保存积分 k (0<=k<=100000)出现的次数,将积分相差n*K的(0<=n<=Max_N/K) 的分为一组,这样就可以得到K组 (数值%K=0,1,...,K-1),在每一组中
用dp找到最优方案。dp[ i ]:某一组前 i 个的最优方案(这里有点难表述)。对于第 i 个有两种选择:选择和 i 位置相差 2*K的对手,这样第 i 个位置的选手也符合条件; 或者选择和
位置 i 积分相差K的选手,这是位置 i 的选手不符合条件。体现在代码中:dp[ i ] = max ( dp[ i -2 ] + cnt[ i ], dp[ i-1 ] )
实现代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int Max_N = ;
const int Max_K = ;
//输入
int N,K;
int A[Max_N+];//A[i]:数值i出现了多少次 void solve()
{
int sum = ;
if( K== )//K==0时单独考虑
{
for(int i=; i<=Max_K; i++){
if( A[i] ) sum++; //相同积分作为匹配的一组,只能选一人
}
printf("%d\n",sum);
return;
}
for(int i=; i<K; i++)//分为K组
{
int cnt[Max_K/K+];//积分为相差n*K的一组
int dp[Max_K/K+];//dp数组
memset(dp,,sizeof(dp));//初始化值为0 int k = ;
for(int j=i; j<=Max_K; j+=K )
{
cnt[k++] = A[j];//其中一组
} dp[] = cnt[];
dp[] = cnt[];//前两个单独考虑 (i-2>=0)
for(int j=; j<k; j++)
{
dp[j] = max( dp[j-]+cnt[j], dp[j-]);
}
sum += dp[k-];
}
printf("%d\n",sum);
} int main()
{
scanf("%d%d",&N,&K);
while( N-- )
{
int a;
scanf("%d",&a);
A[a]++;
} solve(); return ;
}
/*(注释):如果有朋友看到的话,希望可以给我的表述提出自己的意见,或者可以一起学习进步。
蓝桥杯 试题 历届试题 对局匹配 DP解决的更多相关文章
- [蓝桥杯]PREV-26.历届试题_最大子阵
问题描述 给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大. 其中,A的子矩阵指在A中行和列均连续的一块. 输入格式 输入的第一行包含两个整数n, m,分别表示矩阵A的行数和 ...
- [蓝桥杯]PREV-13.历届试题_网络寻路
题目描述: 代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN ...
- [蓝桥杯]PREV-44.历届试题_青蛙跳杯子
问题描述 X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色. X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去. 如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙 ...
- [蓝桥杯]PREV-10.历届试题_幸运数
问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的“筛法”生成 . 首先从1开始写出自然数1,,,,,,.... 就是第一个幸运数. 我们从2这个数开始.把所有序号能被2整除的项删除,变 ...
- [蓝桥杯]PREV-27.历届试题_蚂蚁感冒
问题描述 长100厘米的细长直杆子上有n只蚂蚁.它们的头有的朝左,有的朝右. 每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒. 当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行. 这些蚂蚁中,有1只蚂 ...
- [蓝桥杯]PREV-25.历届试题_城市建设
问题描述 栋栋居住在一个繁华的C市中,然而,这个城市的道路大都年久失修.市长准备重新修一些路以方便市民,于是找到了栋栋,希望栋栋能帮助他. C市中有n个比较重要的地点,市长希望这些地点重点被考虑.现在 ...
- [蓝桥杯]PREV-23.历届试题_数字游戏
问题描述 栋栋正在和同学们玩一个数字游戏. 游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈.栋栋首先说出数字1.接下来,坐在栋栋左手边的同学要说下一个数字2.再下面的一个同学要从上一个同学说的数 ...
- [蓝桥杯]PREV-22.历届试题_国王的烦恼
问题描述 C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在多座桥连接.然而,由于海水冲刷,有一些大桥面临着不能使用的危险. 如果两个小岛间 ...
- [蓝桥杯]PREV-21.历届试题_回文数字
问题描述 观察数字:, 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的.这样的数字叫做:回文数字. 本题要求你找到一些5位或6位的十进制数字.满足如下要求: 该数字的各个数位之和等于输入 ...
随机推荐
- JS面向对象编程之对象
在AJAX兴起以前,很多人写JS可以说都是毫无章法可言的,基本上是想到什么就写什么,就是一个接一个的函数function,遇到重复的还得copy,如果一不小心函数重名了,还真不知道从何开始查找错误,因 ...
- Linux下进程的创建(system(); fork(); exec*())
0. system(); system()函数通过调用shell程序来执行所指向的命令(效率低),相当于先fork(),再execve(): 特点:原进程和子进程各自运行,且原进程需要等子进程运行完后 ...
- Clickhouse 时区转换
Clickhouse 时区转换 ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS). OLAP场景的关键特征 大多数是读请求 数据总是以相当大的批(> 1000 ...
- Chrome最新版如何安装Proxy SwitchyOmega
由于Chrome的代理设置与windows10的1703及以后的版本不兼容,导致无法使用代理功能,给工作带来了很大的不便.最近发现一款不错的Chrome代理插件Proxy SwitchyOmega,由 ...
- Binary Index Tree
0 引言 Leetcode307 这道题给一个可变数组,求从\(i\)到\(j\)的元素之和. 一个naive的做法是,每次查询都从\(i\)累加到\(j\): class NumArray { pu ...
- redis系列之1----redis简介以及linux上的安装
redis简介 redis是NoSQL(No Only SQL,非关系型数据库)的一种,NoSQL是以Key-Value的形式存储数据.当前主流的分布式缓存技术有redis,memcached,ssd ...
- D. Carousel(分类+构造)
\(题目的要求似乎很低:只需要不同类的相邻元素不同色就行了.\) 下面的讨论的话,实际上最后一个点是关键,要想到怎么让最后一个点不开新的颜色就简单了. \(分情况讨论:\) \(\color{Red} ...
- 洛谷p1149
一道很有意思的题目嘞. 这道题目看起来,用搜索似乎无疑了. 我想了这样一个办法(看了很多博客似乎都没用这种方法),可能是觉得太麻烦了吧: 1.我们先把0到9的数字排列,找出排列消耗火柴等于0的序列.这 ...
- 字典树变形 A - Gaby And Addition Gym - 101466A
A - Gaby And Addition Gym - 101466A 这个题目是一个字典树的变形,还是很难想到的. 因为这题目每一位都是独立的,不会进位,这个和01字典树求最大的异或和是不是很像. ...
- matlab 提示 Error using mex No supported compiler or SDK was found 错误的解决办法
在使用simulink的S-Function去调用C程序的时候,需要使用mex指令预先编译C程序,但是出现 Error using mex No supported compiler or SDK w ...