网络流——最小费用流。
好久没写了板子都快忘了。将m个工人拆成n个点,点(i,j)表示让i工人在倒数第j辆车时去修连向这个点的车,那么显而易见代价为j*ti(后面的人要等)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 70 4 #define M 15 5 #define INF 1e9 6 int n,m,cnt=2,ti[M][N],head[5005],p[5005],a[5005],ans,d[5005],S,T; 7 bool vis[5005]; 8 queue<int>q; 9 struct edges{ 10 int fr,to,cap,flow,cost,next; 11 }e[100005]; 12 void inser(int u,int v,int c,int co){ 13 e[cnt]=(edges){u,v,c,0,co,head[u]};head[u]=cnt++; 14 e[cnt]=(edges){v,u,0,0,-co,head[v]};head[v]=cnt++; 15 } 16 bool spfa(){ 17 memset(d,0x3f,sizeof(d)); 18 q.push(S); d[S]=0; a[S]=INF; 19 while(!q.empty()){ 20 int x=q.front(); q.pop(); vis[x]=0; 21 for(int i=head[x];i;i=e[i].next){ 22 if(d[e[i].to]>d[x]+e[i].cost && e[i].cap>e[i].flow){ 23 d[e[i].to]=d[x]+e[i].cost; p[e[i].to]=i; a[e[i].to]=min(a[x],e[i].cap-e[i].flow); 24 if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to); 25 } 26 } 27 } 28 return d[T]<INF; 29 } 30 void minc(){ 31 ans+=a[T]*d[T]; 32 int u=T; 33 while(u!=S){ 34 e[p[u]].flow+=a[T]; 35 e[p[u]^1].flow-=a[T]; 36 u=e[p[u]].fr; 37 } 38 } 39 int main(){ 40 scanf("%d%d",&m,&n); 41 S=0,T=n*m*2; 42 for(int i=1;i<=n;i++) 43 for(int j=1;j<=m;j++) 44 scanf("%d",&ti[j][i]); 45 for(int i=1;i<=m;i++) 46 for(int j=1;j<=n;j++) 47 inser((i-1)*n+j,T,1,0); 48 for(int i=1;i<=n;i++) inser(S,n*m+i,1,0); 49 for(int i=1;i<=n;i++) 50 for(int j=1;j<=m;j++) 51 for(int k=1;k<=n;k++) 52 inser(n*m+i,(j-1)*n+k,1,k*ti[j][i]); 53 while(spfa()) minc(); 54 printf("%.2lf\n",(double)ans/n); 55 return 0; 56 }