同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
最小平均等待时间,答案精确到小数点后2位。
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #define N 100000 using namespace std; int n,m,cnt,tot=-1,dis[N],can[N],last[N]; int next[N*2],point[N],v[N*2],remain[N*2],c[N*2],minn,flow; int mincost=0; bool vis[N]; const int inf=1e9; void add(int x,int y,int z,int k) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z; c[tot]=k; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; c[tot]=-k; } int addflow(int s,int t) { int now=t; int ans=inf; while (now!=s) { ans=min(ans,remain[last[now]]); now=v[last[now]^1]; } now=t; while (now!=s) { remain[last[now]]-=ans; remain[last[now]^1]+=ans; now=v[last[now]^1]; } return ans; } bool spfa(int s,int t) { memset(dis,0x7f,sizeof(dis)); memset(can,0,sizeof(can)); dis[s]=0; can[s]=1; queue<int> p; p.push(s); while(!p.empty()) { int now=p.front(); p.pop(); for (int i=point[now];i!=-1;i=next[i]) if (dis[v[i]]>dis[now]+c[i]&&remain[i]) { dis[v[i]]=dis[now]+c[i]; last[v[i]]=i; if (can[v[i]]==0) { can[v[i]]=1; p.push(v[i]); } } can[now]=0; } if (dis[t]>inf) return false; int k=addflow(s,t); mincost+=k*dis[t]; return true; } void maxflow(int s,int t) { while (spfa(s,t)); } int main() { memset(point,-1,sizeof(point)); memset(next,-1,sizeof(next)); scanf("%d%d",&m,&n); for(int i=1;i<=n;i++) add(0,i,1,0); for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { int x; scanf("%d",&x); for (int k=1;k<=n;k++) add(i,(j-1)*n+k+n,1,x*k); } } cnt=n+n*m+1; for (int i=1;i<=m*n;i++) add(i+n,cnt,1,0); maxflow(0,cnt); //cout<<flow<<endl; printf("%0.2lf\n",(double)(mincost*1.0/n)); }