zoukankan      html  css  js  c++  java
  • BZOJ 1070: [SCOI2007]修车

    Time Limit: 1 Sec  Memory Limit: 128 MB

    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)


    首先将它转化为费用流问题,设计修车数量为流量,总等待时间为费用。

    收先设计一个源点s一个汇点t,然后设计n*m个点表示第j个技术人员倒数第i个修车,然后设计n个点表示每辆车。

    从s往每n*m个点(i,j)个连一条流量1,费用0的边。(表示技术人员可以选择每辆车,但只能修一次,而且在选择第i-1,j前,都要先走i,j,因为是根据最短路做增广路)

    从每个n*m个点(i,j)往n个点k连一条流量为INF,费用为i*time[k][j](time[i][j]表示第i个人修第j辆车的时间,因为车是倒数第i个被修的车,所以这些在它之后修车的人都要等待这段时间。

    然后n个点k往t连一条边流量为1,费用为0,表示每辆车只能被修一次。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    struct X
    {
        int v,f,n,cap,cos;
    }x[66005];
    int ti[65][15],s=1,dis[605],fl[605],pre[605];
    bool vis[605];
    queue<int>q;
    void add(int u,int v,int cap,int cos)
    {
        x[++s].n=x[u].f;
        x[x[u].f=s].v=v;
        x[s].cap=cap;
        x[s].cos=cos;
    }
    bool spfa()
    {
        memset(dis,0x3f,sizeof(dis));
        memset(fl,0,sizeof(fl));
        q.push(1);vis[1]=1;
        dis[1]=0;fl[1]=61;
        for(;!q.empty();q.pop())
        {
            int u=q.front();vis[u]=0;
            for(int i=x[u].f;i;i=x[i].n)
                if(x[i].cap&&dis[x[i].v]>dis[u]+x[i].cos)
                {
                    fl[x[i].v]=min(fl[u],x[i].cap);
                    pre[x[i].v]=i;
                    dis[x[i].v]=dis[u]+x[i].cos;
                    if(!vis[x[i].v])
                    {
                        vis[x[i].v]=1;
                        q.push(x[i].v);
                    }
                }
        }
        return dis[2]<1061109567;
    }
    int main()
    {
        int n,m,cnt,ans=0;
        scanf("%d%d",&m,&n);
        cnt=n+2;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                scanf("%d",&ti[i][j]);
        for(int i=1;i<=n;++i)
        {
            add(i+2,2,1,0);
            add(2,i+2,0,0);
            for(int j=1;j<=m;++j)
            {
                ++cnt;
                add(1,cnt,1,0);
                add(cnt,1,0,0);
                for(int k=1;k<=n;++k)
                {
                    add(cnt,k+2,61,i*ti[k][j]);
                    add(k+2,cnt,0,-i*ti[k][j]);
                }
            }
        }
        while(spfa())
        {
            ans+=dis[2]*fl[2];
            for(int i=2;i!=1;i=x[pre[i]^1].v)
                x[pre[i]].cap-=fl[2],x[pre[i]^1].cap+=fl[2];
        }
        printf("%.2lf",(double)ans/n);
        return 0;
    }
  • 相关阅读:
    第06课:GDB 常用命令详解(下)
    第05课:GDB常用命令详解(中)
    第04课:GDB常用命令详解(上)
    第03课:GDB常用的调试命令概览
    第02课:启动GDB调试
    第01课:调试信息与调试原理
    数据库(二)
    数据库笔记(一)
    acedSSGet 翻译
    ObjectARX动态添加AutoCAD传统下拉菜单入门篇(一)
  • 原文地址:https://www.cnblogs.com/bzmd/p/6363496.html
Copyright © 2011-2022 走看看