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; }