同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
最小平均等待时间,答案精确到小数点后2位。
1.50
解题思路:
把每个工人拆成N个点。记为A[i,j]表示第i个工人修倒数第j辆车。
每个车跟所有N*M个工人拆出的点连边。流量为1,费用为time[i,j]*k。
源和每辆车连边,N*M个点和汇连边,流量都为1,费用同为0。
为什么这么构图呢?
考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。
而这个影响就是后面每个将要修理的车都多等待了time的时间。
其他边流量都为1是显然的,每辆车修一次,每个工人一个时段只能修理一辆车。
注意:bzoj上的double的输出格式要严格"%lf"
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,T,ans=0;
int x[10][61];
int len=1;
struct data
{
int from,to,v,c,next;
}e[200000];
int h[1005];
int dis[1005];
int q[1005];
bool bb[1005];
int pre[1005];
void insert(int x,int y,int v,int c)
{
++len; e[len].from=x; e[len].to=y;
e[len].v=v; e[len].c=c; e[len].next=h[x]; h[x]=len;
}
bool spfa()
{
memset(bb,true,sizeof(bb));
memset(dis,0x7f,sizeof(dis));
int tail=1; int head=0; bb[0]=false; q[tail]=0; dis[0]=0; pre[0]=-1;
while (head!=tail)
{
head=(head+1)%1001;
int u=h[q[head]];
while (u!=0)
{
if (e[u].v && dis[q[head]]+e[u].c<dis[e[u].to])
{
dis[e[u].to]=dis[q[head]]+e[u].c;
pre[e[u].to]=u;
if (bb[e[u].to])
{
bb[e[u].to]=false;
tail=(tail+1)%1001;
q[tail]=e[u].to;
}
}
u=e[u].next;
}
bb[q[head]]=true;
}
if (dis[T]<1000000) return 1;else
return 0;
}
void dfs()
{
int uu=0x7fffffff;
int now=T;
while (pre[now]!=-1)
{
uu=min(e[pre[now]].v,uu);
now=e[pre[now]].from;
}
now=T;
while (pre[now]!=-1)
{
ans+=uu*e[pre[now]].c;
e[pre[now]].v-=uu; e[pre[now]^1].v+=uu;
now=e[pre[now]].from;
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
for (int j=1;j<=n;++j)
{
scanf("%d",&x[j][i]);
}
for (int i=1;i<=n*m;++i)
{
insert(0,i,1,0); insert(i,0,0,0);
}
T=1001;
for (int i=1;i<=m;++i)
{
insert(n*m+i,T,1,0); insert(T,n*m+i,0,0);
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
for (int k=1;k<=m;++k)
{
insert((i-1)*m+j,n*m+k,1,x[i][k]*j);
insert(n*m+k,(i-1)*m+j,0,-x[i][k]*j);
}
while (spfa()){dfs();}
double sss=double(ans)/m;
printf("%.2lf",sss);
}