博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DP题 总结 [更新中]
阅读量:4329 次
发布时间:2019-06-06

本文共 1764 字,大约阅读时间需要 5 分钟。

建设中 ...

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

 

 

一.选学霸

 

题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

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

输入输出样例

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

说明

100%的数据N,P<=20000

 

分析:

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

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

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

AC水题;

 

//By zZhBr#include 
#include
#include
#include
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;}
选学霸

 

转载于:https://www.cnblogs.com/BriMon/p/8933805.html

你可能感兴趣的文章
建议性列表输入文本框
查看>>
RTSP 资料
查看>>
[转]uboot中SPL作用
查看>>
Excel VBA Range对象基本操作应用示例
查看>>
html5拖拽
查看>>
kerboros安装
查看>>
我的学习之路_第二十九章_bootstrap
查看>>
Python读取文件行数不对
查看>>
考研经验交流
查看>>
手游助手应用源码项目
查看>>
职场心得笔记
查看>>
Android context(Application/Activity)与内存泄露
查看>>
mysql 行转列
查看>>
jquery easyui 经验
查看>>
Kafka官方文档翻译——设计
查看>>
本地推送
查看>>
免费的在线文档翻译神器
查看>>
RabbitMQ --- Publish/Subscribe(发布/订阅)
查看>>
细思极恐-你真的会写java吗
查看>>
Jquery 多选下拉列表插件jquery multiselect之如何去掉默认选中项1
查看>>