1. 程式人生 > >01分數規劃

01分數規劃

分解 ++ down blog 1.0 else 01分數規劃 大於 cst

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分數規劃