分数规划裸题
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N=110;
const db INF=1e18;
const db Eps=1e-7;
int k,n,m;
int A[N][N],B[N][N];
db a[N][N];
int f[N],g[N];
db w1[N],w2[N],mn;
int s1,s2;
char v1[N],v2[N];
char dcmp(db a,db b) {
return fabs(a-b)<Eps;
}
char Dfs(int x) {
if(v1[x]) return 0;
v1[x]=1;
for(int i=1;i<=n;i++)
if(!v2[i]) {
if(dcmp(w1[x]+w2[i],a[x][i])) {
v2[i]=1;
if(!f[i]||Dfs(f[i])) {
f[i]=x;g[x]=i;return 1;
}
} else if(w1[x]+w2[i]>a[x][i]) mn=min(mn,w1[x]+w2[i]-a[x][i]);
}
return 0;
}
db Solve() {
memset(w2,0,sizeof(w2));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++) {
db mx=0;
for(int j=1;j<=n;j++) mx=max(mx,a[i][j]);
w1[i]=mx;
}
for(int i=1;i<=n;i++) {
while(1) {
memset(v1,0,sizeof(v1));
memset(v2,0,sizeof(v2));
mn=INF;
if(Dfs(i)) break;
for(int j=1;j<=n;j++) if(v1[j]) w1[j]-=mn;
for(int j=1;j<=n;j++) if(v2[j]) w2[j]+=mn;
}
}
db Ans=0;
for(int i=1;i<=n;i++) Ans+=a[i][g[i]];
return Ans;
}
char Check(db x) {
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=A[i][j]-x*B[i][j];
return Solve()>0;
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
int mx=0;
for(int j=1;j<=n;j++) scanf("%d",&A[i][j]),mx=max(mx,A[i][j]);
s1+=mx;
}
for(int i=1;i<=n;i++) {
int mn=1e4;
for(int j=1;j<=n;j++) scanf("%d",&B[i][j]),mn=min(mn,B[i][j]);
s2+=mn;
}
db l=0,r=(db)s1/s2;
while(r-l>Eps) {
db Mid=(l+r)/2;
if(Check(Mid)) l=Mid;else r=Mid;
}
printf("%.6lf\n",r);
return 0;
}