zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    C++异常:exception
    C++关键字:explicit
    C++关键字:重学记录
    Unity jointmoto
    hashtable和hashmap
    Spring MVC 笔记 概述
    SQL上门2
    面试:A
    Java 初学者
    SQL上门
  • 原文地址:https://www.cnblogs.com/wangyiding2003/p/11551484.html
Copyright © 2011-2022 走看看