• 选学霸


    题目描述
    老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议。所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近
    输入输出格式
    输入格式:
    第一行,三个正整数N,M,K。
    第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N)
    输出格式:
    一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目。(如果有两种方案与M的差的绝对值相等,选较小的一种:)
    输入输出样例
    输入样例#14 3 2
    1 2
    3 4
    输出样例#12
    说明
    100%的数据N,P<=20000
    题面

     解:

    根据题意可得,对于实力相当的一群人,要么不选,要么都选
    我们就把这一群人看成一个物品,
    跑一边背包,体积范围为 0->m*2
    然后枚举所有体积,找到最合适的答案

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int N=2e4+20;
     5 int n,f[N],size[N];
     6 int F(int x)
     7 {
     8     if(x==f[x]) return x;
     9     else return f[x]=F(f[x]);
    10 }
    11 int m,k,a[N],v[N];
    12 int main()
    13 {
    14     scanf("%d%d%d",&n,&m,&k);
    15     for(int i=1;i<=n;++i) f[i]=i;
    16     for(int i=1,x,y;i<=k;++i)
    17     {
    18         scanf("%d%d",&x,&y);
    19         x=F(x);y=F(y);
    20         f[x]=f[y]=min(x,y);
    21     }
    22     for(int i=1,fa;i<=n;++i)
    23     {
    24         fa=F(i);size[fa]++;
    25         if(!v[fa]) v[fa]=1,a[++a[0]]=fa;
    26     }
    27     memset(f,0,sizeof(f));
    28     for(int i=1;i<=a[0];++i)
    29      for(int j=m*2;j>=size[a[i]];--j)
    30       f[j]=max(f[j],f[j-size[a[i]]]+size[a[i]]);
    31     v[0]=0;
    32     for(int j=0;j<=m*2;++j)
    33      if(abs(v[0]-m)>abs(f[j]-m)) v[0]=f[j];
    34      else if(abs(v[0]-m)==abs(f[j]-m)) v[0]=min(v[0],f[j]);
    35     cout<<v[0];
    36     return 0;
    37 }
    代码
  • 相关阅读:
    rowid去重(转)
    Oracle中 row_number() over()分析函数(转)
    oracle分页计算公式
    vue 生产环境和线上环境配置
    vue postcss 样式等比缩放
    element-ui 表单输入手机号验证是否注册或者存在
    使用vue-qr 生成 二维码
    vue下载excel文件,后台传过来的是文件流解决办法
    前端请求接口发送的路径用域名代替ip
    将本地端口映射子域名
  • 原文地址:https://www.cnblogs.com/adelalove/p/8696354.html
Copyright © 2020-2023  润新知