同一时刻有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)
又是一道构图巧妙的费用流题。
把每个技术人员拆成n个点,表示倒数第一个做的、倒数第二个做的、倒数第三个做的......
那么对于一辆车,如果它是倒数第x做的,耗时为y,那么它对总时间的贡献是x*y(这是很好理解的)。
所以我们就可以这样连边,然后跑费用流。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define pa pair<int,int> #define maxn 10000 #define maxm 200000 #define inf 1000000000 using namespace std; struct edge_type { int from,to,next,v,c; }e[maxm]; int head[maxn],dis[maxn],p[maxn],a[61][10]; int n,m,cnt=1,ans=0,s,t; bool inq[maxn]; inline 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; } inline void add_edge(int x,int y,int v,int c) { e[++cnt]=(edge_type){x,y,head[x],v,c};head[x]=cnt; e[++cnt]=(edge_type){y,x,head[y],0,-c};head[y]=cnt; } inline bool spfa() { queue<int> q; memset(inq,false,sizeof(inq)); F(i,1,t) dis[i]=inf; dis[s]=0;inq[s]=true;q.push(s); while (!q.empty()) { int x=q.front();inq[x]=false;q.pop(); for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (e[i].v&&dis[y]>dis[x]+e[i].c) { dis[y]=dis[x]+e[i].c; p[y]=i; if (!inq[y]){inq[y]=true;q.push(y);} } } } return dis[t]!=inf; } inline void mcf() { while (spfa()) { int tmp=inf; for(int i=p[t];i;i=p[e[i].from]) tmp=min(tmp,e[i].v); ans+=dis[t]*tmp; for(int i=p[t];i;i=p[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;} } } int main() { m=read();n=read(); s=m*n+n+1;t=s+1; F(i,1,n) F(j,1,m) a[i][j]=read(); F(i,1,n) add_edge(s,i,1,0); F(i,1,n) F(j,1,m) F(k,1,n) add_edge(i,j*n+k,1,a[i][j]*k); F(i,n+1,m*n+n) add_edge(i,t,1,0); mcf(); printf("%.2f\n",ans*1.0/n); }