POJ 2976 01分数规划

转自魏神:

题目大意就 给定n个二元组(a,b),扔掉k个二元组,使得剩下的a元素之和与b元素之和的比率最大

题目求的是 max(∑a[i] * x[i] / (b[i] * x[i]))  
其中a,b都是一一对应的。 x[i]取0,1  并且 ∑x[i] = n - k;

那么可以转化一下。  令r = ∑a[i] * x[i] / (b[i] * x[i])  则必然∑a[i] * x[i] - ∑b[i] * x[i] * r= 0;(条件1)

并且任意的 ∑a[i] * x[i] - ∑b[i] * x[i] * max(r) <= 0  (条件2,只有当∑a[i] * x[i] / (b[i] * x[i]) = max(r) 条件2中等号才成立)

然后就可以枚举r , 对枚举的r, 求Q(r) = ∑a[i] * x[i] - ∑b[i] * x[i] * r  的最大值,  为什么要求最大值呢?  因为我们之前知道了条件2,所以当我们枚举到r为max(r)的值时,显然对于所有的情况Q(r)都会小于等于0,并且Q(r)的最大值一定是0.而我们求最大值的目的就是寻找Q(r)=0的可能性,这样就满足了条件1,最后就是枚举使得Q(r)恰好等于0时就找到了max(r)。而如果能Q(r)>0
说明该r值是偏小的,并且可能存在Q(r)=0,而Q(r)<0的话,很明显是r值偏大的,因为max(r)都是使Q(r)最大值为0,说明不可能存在Q(r)=0了,需要换方向搜索了、

然后算法框架就出来了。

二分枚举r。对每个r。求出每个a[i] - b[i] * r; 然后排序,将最大的n-k个相加即为最Q(r)的最大值。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<bitset>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define llson j<<1,l,mid
#define rrson j<<1|1,mid+1,r
#define eps 1e-7
#define INF 0x7fffffff
#define maxn 1005
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int n,k;
double a[maxn],b[maxn],val[maxn];
double check(double r)
{
    for(int i=0;i<n;i++)
        val[i]=a[i]-b[i]*r;
    sort(val,val+n,greater<double>());
    double sum=0;
    for(int i=0;i<n-k;i++)
        sum+=val[i];
    return sum;
}
int main()
{
    while(scanf("%d%d",&n,&k)&&(n||k))
    {
        for(int i=0;i<n;i++)
            scanf("%lf",a+i);
        for(int i=0;i<n;i++)
            scanf("%lf",b+i);
        double l=0,r=1,mid;
        while(r-l>eps)
        {
            mid=(l+r)/2.0;
            if(check(mid)>=0) l=mid;
            else r=mid;
        }
        printf("%d\n",(int)(mid*100+0.5));
    }
    return 0;
}
时间: 2024-11-10 07:58:11

POJ 2976 01分数规划的相关文章

POJ 2728 Desert King (最优比率生成树---01分数规划)

题目地址:POJ 2728 01分数规划的应用之一-最优比率生成树. 跟普通的01分数规划类似,只是这题的验证函数改成了最小生成树来验证.弱用的迭代法. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map>

POJ 3621 Sightseeing Cows 【01分数规划+spfa判正环】

题目链接:http://poj.org/problem?id=3621 Sightseeing Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11526   Accepted: 3930 Description Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big ci

POJ - 2976 Dropping tests (01分数规划)

终于把01分数规划这个坑填上了. 题意是有二维平面上的n个向量$(a_i,b_i)$,让你选择其中的m个,使得这些向量和的斜率,即$\frac{\sum a_i}{\sum b_i}$最小. 二分斜率,设$\frac{\sum a_i}{\sum b_i}\geqslant k$,即$\sum a_i\geqslant \sum kb_i$,即$\sum a_i-kb_i\geqslant 0$,选择$a_i-kb_i$前m大的向量判断是否大于0即可. 每次交POJ都得和CE刚上一番... 1

poj 2976 基础01分数规划

这个题算是01分数规划的最基本的应用了, 01分数规划是给你n对数(a1, b1)....(an, bn), 然后让你选择一些数对, 使得sigma(ai)/sigma(bi)最大.这里附上讲解一份, http://blog.csdn.net/hhaile/article/details/8883652, 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #include <iostre

『POJ 2976』Dropping tests (01分数规划)

题目链接 Descrip In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be . Given your test scores and a positive integer k, determine how high you can make your cumulative avera

poj 2718 最优比例生成树(01分数规划)模板

/* 迭代法 :204Ms */ #include<stdio.h> #include<string.h> #include<math.h> #define N 1100 #define eps 1e-10 #define inf 0x3fffffff struct node { int u,v,w; }p[N]; double ma[N][N]; double distance(int i,int j) { return sqrt(1.0*(p[i].u-p[j].u

poj 3621 Sightseeing Cows(最优比例生成环,01分数规划)

http://poj.org/problem?id=3621 大致题意:给出一个有向图,每个点都有一个点权,每条有向边也都有一个边权,要求出一个环使得环中点权之和与边权之和的比值最大. 思路:和最优比率生成树异曲同工.设点权是v[i],边权是e[i].不同的是这里一个是点,一个是边.怎么像生成树一样把这两个值放到一起呢?可以把他们都转化到边上.同样的二分λ,每次给边重新赋权为v[i] - λ*e[i](v[i]是该边终点的点权).因为要求比值最大,那么在这前提下于图中的所有环都<=0, 所以我们

POJ 2728 Desert King(最优比率生成树 01分数规划)

http://poj.org/problem?id=2728 题意: 在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少? 思路: 最优比率生成树,也就是01分数规划,二分答案即可,题目很简单,因为这题是稠密图,所以用prim算法会好点. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector>

poj 2728 Desert King(最优比率生成树,01分数规划)

http://poj.org/problem?id=2728 大致题意:有n个村庄,输入每个村庄的位置和高度,这n个村庄要连在一起,村与村之间的长度为他们之间的欧几里得距离,花费是两村之间的高度差,要求连在一起的花费和与距离和之比的最小值. 思路:明显的最优比率生成树.二分答案λ,每条边重新赋权c[i] - λd[i] ,因为要求比值最小,那么对于所有的生成树,它们的f[λ]必须>=0,所以只需求得基于最小生成树的f'[λ],当f'[λ] = 0时即找到了正解λ*. 二分: #include <