解题思路:    

    把所有的数整理列表,用数组下标表示可能的积分值,对应的数组储存该积分出现的次数,并在第一次输入时记录输入的最大积分值maxn。

    分组,积分差k为2就分两组,一组0,2,4……maxn;一组1,3,5,……maxn这样,用i和j两个下标搜寻,在i和j两个积分制之间比较,留下积分值多的那个。如果i和j中有一个积分值出现了0次当然就可以直接留下不为0的那个数,然后i=i+k,j=i+k继续往后判断;如果i和j表示的积分值都不为0则还需要判断第三个j+k的数出现次数。

    总之,在积分差为k的相邻两个或三个数中留下出现次数多的,把出现次数少的赋值为0,最后在统计数组中留下来的数。

    其实我感觉似乎还有些问题,但不会dp就这么暴力也过了,欢迎大家指教!

    

注意事项:当k为0时需要特殊处理。

参考代码:

// 1842 对局匹配  3/12
#include<iostream>
#include<cstdio>
using namespace std;
int a[100000+5];
int b[100000+5] = {0};
int maxn=0;
int main(){
 int n,k;
 cin>>n>>k;
 for(int i=1;i<=n;i++){
  cin>>a[i];
  if(a[i]>maxn) maxn=a[i];
  b[a[i]]++;
 }
 
 for(int r=0;r<=k;r++){
  if(k==0) k=1;
  for(int i=r,j=i+k;j<=maxn;){
   if(b[i]*b[j]==0){
    i=j;
    j=i+k;
    continue;
   }
   else{
    int p=j+k;
    if(b[p]==0){
     if(b[i]<b[j]) b[i] = 0;
     else b[j] = 0;
     i=p+k;
     j=i+k;
    }
    else{
     int q=b[i]+b[p];
     if(b[j]<q) b[j] = 0;
     else b[i]=b[p]=0;
     i=j;
     j=i+k;
    }
   } 
  }
  if(k==0) break;
 }
 
 int ans=0;
 for(int i=0;i<=maxn;i++) ans+=b[i];
 cout<<ans;
 return 0;
}


点赞(0)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论