[Notes scribbled] 0/1 fractional programming

The first such write blog? In fact, long I wanted to summarize the knowledge but do not really have time to feed ah

This feeling something more practical and simple so a mouth Hu

 

The so-called fractional plan is to seek the optimal ratio, such as a maximum score.

Classic model:

Given several pairs of integers $ a_i, b_i $, to choose the required pairs of the $ \ frac {\ sum a_i} {\ sum b_i} $ maximum.

For that matter, we might xjb guess randomly select a value $ L $, then consider:

Whether a set of solutions exist to meet $ \ sum a_i-L * b_i \ ge 0 $

The top of the Kichiku persimmon look, you can get $ \ sum a_i- \ sum L * b_i \ ge 0 $,

Eventually become $ \ frac {\ sum a_i} {\ sum b_i} \ ge L $

What if qualified solution exists, it shows there is greater than the ratio of L, L than the maximum that is what we ask to be small.

What if it does not exist? L is larger than the maximum value of the pictures.

Sound familiar? Obviously this thing can do half the answer, because there is monotonic relationship between L and solution.

So how to determine $ \ sum a_i-L * b_i \ ge 0 $ whether it solvable? Count on $ \ sum a_i-L * b_i $ maximum positive and negative does not look like it.

This is a good find ah, because the $ a_i-L * b_i $ can be directly counted, just take a look at what you can take and which not attain the most value.

 

So get questions directly dichotomous answers, determine whether the $ \ sum a_i-mid * b_i $ maximum non-negative, is it l = mid, or r = mid (must pay attention to two points with integer dichotomy of different real number range)

The final l is the optimal ratio.

 

Lost one example [bzoj4753] Optimal Group

Very bare fraction of planning needs to be done but check the trees rely backpack, each made into a dfs order $ O (nK) $ dp can be.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=2505;
const double eps=1e-5,inf=19260817.233;
int K,n,fa[N];
double now[N],dp[N][N],w[N],val[N],maxx=-inf;
int to[N<<1],nxt[N<<1],head[N],tot;
int dfn[N],rev[N],num,size[N];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
void add(int x,y;++ tot] =
    to [
{y)int
    nxt[tot]=head[x];
    head[x]=tot;
}
void dfs(int x)
{
    size[x]=1;
    dfn[x]=num;
    rev[num++]=x;
    for(int i=head[x];i;i=nxt[i])
        dfs(to[i]),size[x]+=size[to[i]];
}
double DP(double x)
{
    for(int i=1;i<=n;i++)
        now[i]=val[rev[i]]-x*w[rev[i]];
    for(int i=1;i<=n+1;i++)
        for(int j=0;j<=K+1;j++)
            dp[i][j]=-inf;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=min(i,K+1);j++)
            dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]+now[i]),
            dp[i+size[rev[i]]][j]=max(dp[i+size[rev[i]]][j],dp[i][j]);
    return dp[n+1][K+1];
}
int main()
{
    K=read();n=read();
    for(int i=1;i<=n;i++)
    {
        w[i]=(double)read();
        val[i]=(double)read(),maxx=max(maxx,val[i]);
        fa[i]=read();
        add(fa[i],i);
    }
    dfs(0);
    double l=0.0,r=maxx;
    while(r-l>eps)
    {
        double mid=(l+r)/2.0;
        if(DP(mid)>=eps)l=mid;
        else r=mid;
    }
    printf("%.3lf",l);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Rorschach-XR/p/11291312.html