原题链接:蓝桥杯2017年第八届真题-对局匹配
解题思路:
把所有的数整理列表,用数组下标表示可能的积分值,对应的数组储存该积分出现的次数,并在第一次输入时记录输入的最大积分值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 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复