您的位置:首页 > 大数据 > 人工智能

poj 2010--Moo University - Financial Aid

2014-02-25 20:23 253 查看
给出c组数,要在其中选n个(n为奇数),使其分数的中位数最大,同时这n个数的费用之和不能超过f,如果不能满足就输出-1

http://poj.org/problem?id=2010

这道题想了好久。。WA了好几遍,还TLE了一次>_<

其实就是大根堆,可以用stl中的优先队列

先按分数排序,

然后用一个数组dp[i][j], dp[i][0]表示i之前费用最小的n/2个数之和,dp[i][1]表示i之后费用最小的n/2个数之和

将n/2个数保存在大根堆里

先从前往后扫一遍,求出dp[i][0],更新的时候和堆的根比较(也就是优先队列的队首)。如果小于根,就将根删除,将更小的元素加进去

再从后向前扫一遍,同理求出dp[i][1]。

(我一直纠结与如何同时求出dp[i][0]和dp[i][1]。。真是。。。(@﹏@)~ )

最后再从后向前扫一遍,找到满足条件的最大值即可~

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n, c, f;
ll dp[100000 + 10][2];
struct node{
ll sco, w;
}cow[100000 + 10];
bool cmp(node a, node b){
return a.sco < b.sco;
}
int main(){
scanf("%I64d%I64d%I64d", &n, &c, &f);
for(int i=0; i<c; i++){
scanf("%I64d%I64d", &cow[i].sco, &cow[i].w);
dp[i][0] = dp[i][1] = 0;
}
priority_queue<ll> Q1, Q2;
ll ans = -1, tmp = n / 2;
sort(cow, cow + c, cmp);
for(int i=0; i<n/2; i++){
dp[tmp][0] += cow[i].w;
Q1.push(cow[i].w);
}
for(int i=tmp+1; i<c; i++){
ll now = Q1.top();
dp[i][0] = dp[i - 1][0];
if(cow[i - 1].w < now){
Q1.pop();
Q1.push(cow[i -1].w);
dp[i][0] += cow[i - 1].w - now;
}
}
tmp = c - 1 - n / 2;
for(int i=c-1; i>tmp; i--){
dp[tmp][1] += cow[i].w;
Q2.push(cow[i].w);
}
for(int i=tmp-1; i>=0; i--){
ll now = Q2.top();
dp[i][1] = dp[i + 1][1];
if(cow[i + 1].w < now){
Q2.pop();
Q2.push(cow[i + 1].w);
dp[i][1] += cow[i + 1].w - now;
}
}
for(int i=tmp; i>=n/2; i--){
if(dp[i][0] + dp[i][1] + cow[i].w <= f){
ans = cow[i].sco;
break;
}
}
printf("%I64d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息