P2053 [SCOI2007]修车

题目描述

同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。

说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

输入格式

第一行有两个数M,N,表示技术人员数与顾客数。

接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

输出格式

最小平均等待时间,答案精确到小数点后2位。

输入输出样例

输入 #1
2 2
3 2
1 4
输出 #1
1.50

说明/提示

(2<=M<=9,1<=N<=60), (1<=T<=1000)

思路

对于每一位师傅,都有ki个车等待修理,那么第i辆车修理的时间对答案的贡献应该为(ki-i+1)*ti,如果倒推,则为倒数第i辆车的贡献为i*ti,可以直接计入答案。所以对于所有的车,在每一位师傅上分别有n*m种情况,因此我们可以对每个师傅的每个时刻和每一辆车进行建边,最后跑最大流最小费用进行求解。

代码

#include<bits/stdc++.h>
#define N 10700
#define M 107000
#define inf 1<<29
using namespace std;
struct node{
    int y,z,p,next;
}e[M*2];
int tot=1,head[N],maxflow=0,ans=0;
int n,m,s,t;
void add(int x,int y,int z,int p){
    e[++tot].y=y;e[tot].z=z;e[tot].p=p;
    e[tot].next=head[x];head[x]=tot;
}
int incf[N],v[N],pre[N],d[N];
bool spfa(){
    queue<int> q;
    memset(d,0x3f,sizeof(d));// 0xcf
    memset(v,0,sizeof(v));
    q.push(s);d[s]=0;v[s]=1;
    incf[s]=inf;
    while(q.size()){
        int x=q.front();v[x]=0;q.pop();
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y,z=e[i].z;
            if(!z) continue;
            if(d[y]>d[x]+e[i].p){//d[y]<d[x]+e[i].p
                d[y]=d[x]+e[i].p;
                incf[y]=min(incf[x],z);
                pre[y]=i;
                if(!v[y]) v[y]=1,q.push(y);
            }
        }
    }
    if(d[t]==0x3f3f3f3f) return false;//0xcfcfcfcf
    return true;
}
void update(){
    int x=t;
    while(x!=s){
        int i=pre[x];
        e[i].z-=incf[t];
        e[i^1].z+=incf[t];
        x=e[i^1].y; 
    }
    maxflow+=incf[t];
    ans+=d[t]*incf[t];
}
int main()
{
    scanf("%d%d",&m,&n);s=n+n*m+1,t=n+n*m+2;
    for(int i=1;i<=n;i++)add(s,i,1,0),add(i,s,0,0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int c;scanf("%d",&c);
            for(int k=1;k<=n;k++){
                add(i,j*n+k,1,c*k);
                add(j*n+k,i,0,-1*c*k);
            }
        }
    }
    for(int i=1;i<=n*m;i++){
        add(n+i,t,1,0);add(t,n+i,0,0);
    }
    while(spfa()) update();
    printf("%.2lf",(double)ans/n);
    return 0;
}

 

posted @ 2019-09-19 18:00  wangyiding  阅读(110)  评论(0编辑  收藏  举报