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

POJ-2010 Moo University - Financial Aid

2015-12-30 16:38 555 查看
题意:c头牛,每头牛有个智力值和需求值,选出n(为奇数)头牛,在需求值总和不超过F的情况。选出的c头牛中,中位数最大。。

思路:好难。

参考博客:点击打开链接

第一种思路: 优先队列。。

思路:按照智力排序。

一个lower数组,一个upper数组。

lower[i]表示从前i个里面选出n/2头牛的最少需求和。

upper[i]表示从后i个里面选出n/2头牛的最少需求和。

从大到小枚举每个数为中位数的情况。。满足就输出。。

思路的理解:N选出N头牛,其中的中位数绝对是C头牛的前面N/2个,后面的N/2个。枚举即可。

学会一些技巧。。。

#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include<sstream>
#include <cmath>
using namespace std;
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define INF 1e9*2+10
#define sq(x) (x)*(x)
#define eps (1e-10)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

const int maxn=100010;

int N,C,F;
pair<int,int> cow[maxn];

int lower[maxn],upper[maxn];

int main()
{
cin>>N>>C>>F;
int half=N/2;
for(int i=0;i<C;i++) cin>>cow[i].fs>>cow[i].se;
sort(cow,cow+C);
int total=0;
priority_queue<int> q;
for(int i=0;i<C;i++)
{
lower[i]=(q.size()==half?total:INF);//技巧
q.push(cow[i].se);
total+=cow[i].se;
if(q.size()>half)
{
total-=q.top();
q.pop();
}
}
total=0;
while(!q.empty()) q.pop();
for(int i=C-1;i>=0;i--)
{
upper[i]=(q.size()==half?total:INF);//技巧
q.push(cow[i].se);
total+=cow[i].se;
if(q.size()>half)
{
total-=q.top();
q.pop();
}
}
int result=-1;
for(int i=C-1;i>=0;i--)
{
if(lower[i]+cow[i].se+upper[i]<=F)
{
result=cow[i].fs;
break;
}
}
cout<<result<<endl;
return 0;
}


二分搜索法

在分别排序分数和学费之后,以分数为界限将牛分为左右两个区间,统计左区间符合条件的数目left和右区间的数目right。讨论left 和right是否满足条件。以此为基础二分,实际上下面的谓词逻辑可以优化,但是目前看起来比较好懂。

感觉太麻烦。。。。。参考博客里面有。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: