同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入:
2 2 3 2 1 4输出:
1.50
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
首先可以发现如果直接进行暴力的话那么枚举每个人的复杂度是O(M*2^N)该复杂度令人难以接受,
每个人只可以被使用一次。。。可以通过网络流来限制流量,然后如果每个人跑一次网络流。。。根本不能友好的玩耍。
但是如果每个人最多处理N辆车,那么可以处理对于每一个人来说第K辆车是当前这个人的倒数第i个处理的那么就相当于这个人第N-i+1个节点,因为是倒数第i个后面还有i-1个车等待当前工作人员处理,那么浪费的时间就是(i-1)*T+T 加一个T的原因是当前处理现在这辆车也要耗费时间
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 2000;
const int INF = 1e9+7;
const int MAXM = 100000;
struct node{
int v, cost, cap;
node *next, *back;
}Edges[MAXM*2+10], *ecnt=Edges, *adj[MAXN+10];
int dis[MAXN+10], res[MAXN+10];
node *Fa[MAXN+10];
void addedge(int u, int v, int ca, int co){
++ecnt;
ecnt->v = v;
ecnt->cap = ca;
ecnt->cost = co;
ecnt->next = adj[u];
ecnt->back = ecnt+1;
adj[u] = ecnt;
++ecnt;
ecnt->v = u;
ecnt->cap = 0;
ecnt->cost = -co;
ecnt->next = adj[v];
ecnt->back = ecnt-1;
adj[v] = ecnt;
}
int ncnt, s, t;
bool SPFA(){
for(int i=1;i<=ncnt;i++)
dis[i]=INF;
dis[s] = 0;
queue<int> que;
que.push(s);
res[s] = INF;
while(!que.empty()){
int u = que.front();
que.pop();
for(node *p=adj[u];p;p=p->next){
if(p->cap == 0) continue;
if(dis[p->v] <= dis[u] + p->cost) continue;
dis[p->v] = dis[u] + p->cost;
Fa[p->v] = p;
res[p->v] = min(res[u], p->cap);
que.push(p->v);
}
}
return !(dis[t] == INF);
}
int work(){
int ret = 0;
while(SPFA()){
ret += res[t] * dis[t];
int now = t;
while(now != s){
Fa[now]->cap -= res[t];
Fa[now]->back->cap += res[t];
now = Fa[now]->back->v;
}
}
return ret;
}
int n, m;
int main(){
while(~scanf("%d%d", &m, &n)){
memset(adj, 0, sizeof adj);
ecnt=Edges;
s=1, t=m*n+n+2;ncnt = m*n+n+2;
int tmp;
for(int i=1;i<=n;i++){
addedge(1, i+1, 1, 0);
for(int j=1;j<=m;j++){
scanf("%d", &tmp);
for(int k=1;k<=n;k++)
addedge(i+1, 1+n*j+k, 1, (n-k)*tmp+tmp);
}
}
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
addedge(1+n*i+j, t, 1, 0);
printf("%.2lf\n", work()*1.0/n);
}
return 0;
}