码迷,mamicode.com
首页 > 其他好文 > 详细

01分数规划

时间:2018-02-15 13:56:31      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:clu   分数规划   一个   gpo   ++   就是   scanf   mes   code   

01分数规划,就是这样一个东西
\(max(\frac{\sum ai * xi}{\sum bi * xi})\),其中\(xi \in {0,1}\)
简而言之,就是在n个物品中选出任意几个【或者可以有限制选多少个】,使得其两种权值a,b的比值最大

这样的问题可以二分解决
假如有这样一道裸题:POJ2976,选n - k个物品使得比值最大
我们二分出r,
若存在\(\frac{\sum ai * xi}{\sum bi * xi} >= r\),则r可行
变形得\(\sum ai * xi - r * \sum bi * xi >= 0\)
我们就可以把每件物品看做是权值\(ai - bi * r\),排个序看看前n - k大之和是否大于0即可

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
const int maxn = 1005,maxm = 100005,INF = 1000000000;
int n,k;
double A[maxn],B[maxn],t[maxn];
bool check(double x){
    REP(i,n) t[i] = A[i] - x * B[i];
    sort(t + 1,t + 1 + n);
    double sum = 0;
    for (int i = k + 1; i <= n; i++) sum += t[i];
    return sum > 0;
}
int main(){
    while (~scanf("%d%d",&n,&k) && (n || k)){
        REP(i,n) scanf("%lf",&A[i]);
        REP(i,n) scanf("%lf",&B[i]);
        double l = 0,r = 1.0,mid;
        while (r - l > 0.0000001){
            mid = (l + r) / 2;
            if (check(mid)) l = mid;
            else r = mid;
        }
        printf("%d\n",(int)round(l * 100));
    }
    return 0;
}

01分数规划

标签:clu   分数规划   一个   gpo   ++   就是   scanf   mes   code   

原文地址:https://www.cnblogs.com/Mychael/p/8449452.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!