• 修车(bzoj 1070)


    Description

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

    Input

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

    Output

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

    Sample Input

    2 2
    3 2
    1 4

    Sample Output

    1.50

    HINT

    数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

    /*
        如果某个工人修一辆车花费t的时间,并且这是他修的倒数第k辆车,那么对答案的贡献是k*t。
        我们把每个工人差拆成n个,第k各代表他修倒数第k辆车时的状态,然后建图跑费用流。 
    */
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define N 1010
    #define M 1000010
    #define inf 1000000000
    using namespace std;
    int t[70][70],head[N],dis[N],inq[N],fa[N],n,m,S,T,cnt=1;
    struct node{int v,f,w,pre;}e[M];
    queue<int> q;
    void add(int u,int v,int f,int w){
        e[++cnt].v=v;e[cnt].f=f;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt;
        e[++cnt].v=u;e[cnt].f=0;e[cnt].w=-w;e[cnt].pre=head[v];head[v]=cnt;
    }
    bool spfa(){
        for(int i=0;i<=T;i++) dis[i]=inf;
        q.push(S);dis[S]=0;
        while(!q.empty()){
            int u=q.front();q.pop();inq[u]=0;
            for(int i=head[u];i;i=e[i].pre)
                if(e[i].f&&dis[e[i].v]>dis[u]+e[i].w){
                    dis[e[i].v]=dis[u]+e[i].w;
                    fa[e[i].v]=i;
                    if(!inq[e[i].v]){
                        inq[e[i].v]=1;
                        q.push(e[i].v);
                    }
                }
        }
        return dis[T]!=inf;
    }
    int updata(){
        int i=fa[T],x=inf;
        while(i){
            x=min(x,e[i].f);
            i=fa[e[i^1].v];
        }
        i=fa[T];
        while(i){
            e[i].f-=x;
            e[i^1].f+=x;
            i=fa[e[i^1].v];
        }
        return x*dis[T];
    }
    int main(){
        scanf("%d%d",&m,&n);
        S=0;T=n*m+n+1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&t[i][j]);
        for(int i=1;i<=n*m;i++)
            add(S,i,1,0);
        for(int i=n*m+1;i<=n*m+n;i++)
            add(i,T,1,0);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    add((i-1)*n+j,n*m+k,1,t[k][i]*j);
        int ans=0;
        while(spfa())
            ans+=updata();
        printf("%.2lf",(double)ans/n);
        return 0;
    }
  • 相关阅读:
    cf605 div3
    how to find Longest Increasing Subsequence Size
    luogu1641 [SDOI2010]生成字符串
    luogu1441 砝码称重
    luogu4218 [JSOI2008] 最小生成树计数
    luogu1514 引水入城
    luogu1312 Mayan游戏 剪枝
    luogu1081 开车旅行 树上倍增
    luogu1052 过河
    luogu1026 统计单词个数
  • 原文地址:https://www.cnblogs.com/harden/p/6720324.html
Copyright © 2020-2023  润新知