分析
将m个车拆为n*m个点
相当于将每个车在不同的时段修分成新的车
在第n-i个时段会对之后的车总共造成i*t[i]的贡献
人向车连边然后分别连st即可
代码
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int n,m,s,t,tot,ans,G,pr[100100],d[100100],iq[100100],ano[100100],cnt,id[110][110];
int head[100100],nxt[100100],f[100100],w[100100],to[100100],mf[100100],frm[100100];
inline void add(int x,int y,int z,int c){
nxt[++cnt]=head[x];head[x]=cnt;to[cnt]=y;f[cnt]=z;w[cnt]=c;frm[cnt]=x;
nxt[++cnt]=head[y];head[y]=cnt;to[cnt]=x;f[cnt]=0;w[cnt]=-c;frm[cnt]=y;
ano[cnt]=cnt-1;ano[cnt-1]=cnt;
}
queue<int>q;
inline void work(){
int i,j,k;
while(1){
for(i=0;i<=tot;i++)d[i]=inf,iq[s]=0;
d[s]=0;
iq[s]=1;
q.push(s);
mf[s]=inf;
while(!q.empty()){
int x=q.front();
q.pop();
iq[x]=0;
for(i=head[x];i;i=nxt[i]){
int y=to[i],z=w[i];
if(f[i]&&d[y]>d[x]+z){
d[y]=d[x]+z;
mf[y]=min(mf[x],f[i]);
pr[y]=i;
if(!iq[y])iq[y]=1,q.push(y);
}
}
}
if(d[t]>=inf)return;
int x=pr[t];
while(x){
ans+=w[x]*mf[t];
f[x]-=mf[t];
f[ano[x]]+=mf[t];
x=pr[frm[x]];
}
}
}
int main(){
int i,j,k;
scanf("%d%d",&m,&n);
s=0,t=1;
tot=1;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
id[i][j]=++tot,add(tot,t,1,0);
for(i=1;i<=n;i++){
int x,y;
x=++tot;
add(s,x,1,0);
for(j=1;j<=m;j++){
scanf("%d",&G);
for(k=1;k<=m;k++)add(x,id[j][k],1,G*k);
}
}
work();
printf("%0.2lf
",(double)ans/n);
return 0;
}