zoukankan      html  css  js  c++  java
  • DP题 总结 [更新中]

    建设中 ...

     预防针 : 本蒟蒻代码风格清奇(⊙﹏⊙)b

    一.选学霸

    题目描述

    老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议。所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近

    输入输出格式

    输入格式:

    第一行,三个正整数N,M,K。

    第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N)

    输出格式:

    一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目。(如果有两种方案与M的差的绝对值相等,选较小的一种:)

    输入输出样例

    输入样例#1: 
    4 3 2
    1 2
    3 4
    输出样例#1: 
    2

    说明

    100%的数据N,P<=20000

    分析:

    看到这题第一下想出的就是并查集, 但仔细想想很容易想到背包问题。

    因为所有水平一样的人必须一起选, 所以, 把水平一样的人看成一件物品。再01背包转移。

    注意此时的最大体积应该为2*m(很容易想到)。最后再枚举体积。最后再注意一下差值一样时取最小。

    AC水题;

    //By zZhBr
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    
    int n, m, k;
    
    int f[20010];
    
    inline int find(int x)
    {
        return x == f[x] ? f[x] : f[x] = find(f[x]);
    }
    
    int a[20010];
    
    int dp[20010];
    
    int num[20010];
    int vis[20010]; 
    
    int cnt;
    
    int main()
    {
        scanf("%d%d%d", &n, &m, &k);
        
        for(register int i = 1 ; i <= n ; i ++) f[i] = i;
        
        for(register int i = 1 ; i <= k ; i ++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            
            int fx = find(x), fy = find(y);
            f[fx] = fy;
            
        }
        
        for(register int i = 1 ; i <= n ; i ++)
        {
            int fa = find(i);
            num[fa]++;
            if(!vis[fa]) 
            {
                vis[fa] = 1;
                a[++cnt] = fa;
            }
            
        }
        
        for(register int i = 1 ; i <= cnt ; i ++)
        {
            for(register int j = m * 2 ; j >= num[a[i]] ; j --)
            {
                dp[j] = max(dp[j], dp[j-num[a[i]]] + num[a[i]]);
            }
        }
        
        int ans = 0;
        
        for(register int i = 0 ; i <= m * 2 ; i ++)
        {
            if(abs(ans - m) > abs(dp[i] - m)) ans = dp[i];
            else if(abs(ans - m) == abs(dp[i] - m)) ans = min(ans, dp[i]);
        }
        
        printf("%d", ans);
        
        return 0;
    }
    选学霸
  • 相关阅读:
    20165329 《Java程序设计》第九周学习总结
    20165329 四则运算2
    20165329 第八周补做
    20165329 《Java程序设计》第八周学习总结
    2017-2018-2 学号20165329 实验二《Java面向对象程序设计》实验报告
    20165329 结对编程项目-四则运算
    20165329 第七周学习总结
    20165329 第六周学习总结
    20165329 实验一 java环境的熟悉
    20165329 第五周学习总结
  • 原文地址:https://www.cnblogs.com/BriMon/p/8933805.html
Copyright © 2011-2022 走看看