挑战程序设计竞赛2.4习题:Moo University - Financial Aid POJ - 2010

Bessie noted that although humans have many universities they can attend, cows have none. To remedy this problem, she and her fellow cows formed a new university called The University of Wisconsin-Farmside,"Moo U" for short.

Not wishing to admit dumber-than-average cows, the founders created an incredibly precise admission exam called the Cow Scholastic Aptitude Test (CSAT) that yields scores in the range 1..2,000,000,000.

Moo U is very expensive to attend; not all calves can afford it.In fact, most calves need some sort of financial aid (0 <= aid <=100,000). The government does not provide scholarships to calves,so all the money must come from the university‘s limited fund (whose total money is F, 0 <= F <= 2,000,000,000).

Worse still, Moo U only has classrooms for an odd number N (1 <= N <= 19,999) of the C (N <= C <= 100,000) calves who have applied.Bessie wants to admit exactly N calves in order to maximize educational opportunity. She still wants the median CSAT score of the admitted calves to be as high as possible.

Recall that the median of a set of integers whose size is odd is the middle value when they are sorted. For example, the median of the set {3, 8, 9, 7, 5} is 7, as there are exactly two values above 7 and exactly two values below it.

Given the score and required financial aid for each calf that applies, the total number of calves to accept, and the total amount of money Bessie has for financial aid, determine the maximum median score Bessie can obtain by carefully admitting an optimal set of calves.

Input

* Line 1: Three space-separated integers N, C, and F

* Lines 2..C+1: Two space-separated integers per line. The first is the calf‘s CSAT score; the second integer is the required amount of financial aid the calf needs

Output

* Line 1: A single integer, the maximum median score that Bessie can achieve. If there is insufficient money to admit N calves,output -1.

Sample Input

3 5 70
30 25
50 21
20 20
5 18
35 30

Sample Output

35

Hint

Sample output:If Bessie accepts the calves with CSAT scores of 5, 35, and 50, the median is 35. The total financial aid required is 18 + 30 + 21 = 69 <= 70.

注意点,由于分数区间过大,没有办法dp实现,只能从个数等数量级少的入手。

想到要求出中位数,中间值难求,不知道,但是我们知道中间值有范围,我们先按照分数排序

由于中位数之前有n/2个数,之后也有n/2个数,不如直接遍历中位数的所有可能,求出前n/2的最小和以及后n/2的最小和,两者加上中位数的值如果小于f,那么就有可能选中,答案就是在可能选中的当中中位数最大的那个。

于是乎我们知道中位数在排序后cows[n/2] ~ cows[c - n/2]的范围内(数组从0开始到n-1结束),每一种情况计算前后选取n/2个分别使得前后选取的n/2个的和最小。

如果中位数是cows[n/2](也就是中位数可取范围的最小那个)那么中位数之前一共有n/2的数,所有在中位数之前选取n/2个数就只能是把之前的全选,和为他们的和。如果中位数往后一个(也就是可选范围第二小的),那么中位数之前一共有n/2+1个数,我们要选取其中n/2个数使得这些数和最小,我们可以从上一个状态推出答案——因为上一个状态是全选,我们这次会多一个数剩余,我们肯定要剩余需要资助最多的奶牛,我们比较比上一次新增的cows[n/2]奶牛的花费与之前n/2个中需要资助最大的奶牛的花费进行比较,看看哪个大。如果前者大,我们就留下新增的那头奶牛不选,因为它的花费比cows[0]~cows[n/2-1]中任何一头奶牛所要的资费都要大;如果后者大,那么把之前状态中n/2个中需要最大资助的奶牛不要,少的一个我们就换成cows[n/2]这个新增的奶牛就可以使得前面选取n/2的和最少,以此类推,每次都找到上一次选择的n/2个中最大的与新增的进行比较进行替换,为了节省时间和不必要的开支,之前的状态可以用数据结构进行保存,为了方便找到最大值,我们采用优先队列进行维护。

AC代码:

#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;
struct Cow{
	int score;
	int need;
	friend bool operator<(Cow x, Cow y)
	{
		return x.score < y.score;
	}
}cows[100005];//记录奶牛状态,score分数,need需要的资助金额
priority_queue<int> pq_pre, pq_pos;//pq_pre:从中位数之前取n/2个数,使得资助金额和最小的优先队列,pq_pos从中位数之后取n/2个数
int pre[100005];//在中位数为i的时候,从i之前取n/2个数,使得资助金额和最小的值
int pos[100005];
int total, ans = -1;//如果答案不存在就是-1,total是中间变量,计算pre或者是pos的值的
int cow_num;//单纯的计数功能
int main(void)
{
	int n, c, f;
	scanf("%d %d %d", &n, &c, &f);
	for(int i = 0; i < c; i++)
	{
		scanf("%d %d", &cows[i].score, &cows[i].need);
	}
	sort(cows, cows + c);//按分数排序
	for(int i = 0; i < n / 2; i++)//初始化把前n/2个都加起来,也就是当中位数为从cows[n/2].need时前面n/2的和的最小值
	{
		total += cows[i].need;
		pq_pre.push(cows[i].need);//记得前面的也要放进队列
	}
	for(int i = n / 2; i < c - n / 2; i++)
	{
		pre[i] = total;
		if(!pq_pre.empty() && cows[i].need < pq_pre.top())//如果队列为非空(防止c == 1的情况)且新增的奶牛比在队列的资助最大奶牛的资助要小,那么就删掉之前队列最大的,换上这一头新的奶牛
		{
			total -= pq_pre.top();
			pq_pre.pop();
			total += cows[i].need;
			pq_pre.push(cows[i].need);
		}
	}
	total = 0;
	for(int i = c - 1; i >= c - n / 2; i--)//同理计算当中位数为cows[c - n/2 - 1]时后n/2头
	{
		total += cows[i].need;
		pq_pos.push(cows[i].need);
	}
	for(int i = c - n / 2 - 1; i >= n / 2; i--)
	{
		pos[i] = total;
		if(!pq_pos.empty() && cows[i].need < pq_pos.top())
		{
			total -= pq_pos.top();
			pq_pos.pop();
			total += cows[i].need;
			pq_pos.push(cows[i].need);
		}
	}
	for(int i = c - n / 2 - 1; i >= n / 2; i--)//从大到小遍历,找到的第一个符合体条件的情况就是答案
		if(pre[i] + pos[i] + cows[i].need <= f)
		{
			ans = cows[i].score;
			break;
		}
	printf("%d\n", ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/jacobfun/p/12244509.html

时间: 2024-08-29 10:23:11

挑战程序设计竞赛2.4习题:Moo University - Financial Aid POJ - 2010的相关文章

Moo University - Financial Aid (poj 2010 优先队列 或者 二分)

Language: Default Moo University - Financial Aid Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5551   Accepted: 1663 Description Bessie noted that although humans have many universities they can attend, cows have none. To remedy this p

挑战程序设计竞赛3.1习题:Moo University - Financial Aid POJ - 2010

(原题见POJ2010) 这道题我之前采用了优先队列+预处理的方法求解(https://www.cnblogs.com/jacobfun/p/12244509.html),现在用二分的办法进行求解. 一开始我很纳闷,采用二分求解本题,如果二分的mid值不符合条件,按照二分右边界应该为mid - 1(我采用前闭后闭的二分),那么如果mid + xxx(xxx大于0)可以呢?(考虑mid不行是因为左边最小加起来大了,mid ~ mid + xxx中有极小值,使得mid + xxx的左边可以满足,那么

Moo University - Financial Aid POJ 2010(枚举)

原题 题目链接 题目分析 题目要求取中位数,我们可以枚举以每个牛的分数作为中位数,然后选出最省钱的方案,最后只需要看花钱数不超过F中的最高的中位数分数即可.说一下具体实现,先对所有牛按分数从小到大排序,选出最省钱的方案可以用优先队列来选,设half=n/2,当优先队列的牛超过half个的时候就把一个花费最多的弹出去,这样从小到大遍历一遍就可以记录分数比中位数小的那些牛的花费,记为lower[i],从大到小遍历一遍就可以记录分数比中位数大的那些牛的花费,记为upper[i],最后这个方案的总花费就

挑战程序设计竞赛2.3习题:Making the Grade POJ - 3666

A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ would like t

poj2010 Moo University - Financial Aid

Moo University - Financial Aid 题意: 一个私立学校的学生要申请奖学金,而学校的金额有限.因此,学校希望在金额不超过F的情况下从C中选得N对数. 给出三个数N,C,F.分别代表在C对数中要取得N对数. 而每对数分别代表成绩,跟申请金额.要求取得N对数中的总金额不超过F的条件下,然取得中间的以为学生的成绩最高.(N为even) 算法分析: 本题有两种解法,一种是用优先队列,一种是二分; 一.利用堆实现 先说堆的实现方法,我们能够现对头尾的N/2进行处理,由于头尾的N/

POJ 2010 Moo University - Financial Aid( 优先队列+二分查找)

POJ 2010 Moo University - Financial Aid 题目大意,从C头申请读书的牛中选出N头,这N头牛的需要的额外学费之和不能超过F,并且要使得这N头牛的中位数最大.若不存在,则输出-1(一开始因为没看见这个,wa了几次). 这个题的第一种做法就是用两个优先队列+贪心. /* * Created: 2016年03月27日 14时41分47秒 星期日 * Author: Akrusher * */ #include <cstdio> #include <cstdl

POJ2010 Moo University - Financial Aid(二分法)

题目地址 分析:如果用二分法,关键是score和aid分开排序,score排序是为了充分利用中位数的性质,这样就可以确定m左右必须各选N/2个,到这之后有人是用dp求最优解,可以再次按照aid排序一次,可以直接确定最优解(肯定是从最小的开始选择!): 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 using namespace std; 5 int N, C, F; 6 const i

poj 2010 Moo University - Financial Aid(优先队列(最小堆)+ 贪心 + 枚举)

Description Bessie noted that although humans have many universities they can attend, cows have none. To remedy this problem, she and her fellow cows formed a new university called The University of Wisconsin-Farmside,"Moo U" for short. Not wish

poj2010(Moo University - Financial Aid)优先队列

Description Bessie noted that although humans have many universities they can attend, cows have none. To remedy this problem, she and her fellow cows formed a new university called The University of Wisconsin-Farmside,"Moo U" for short. Not wish