zoukankan      html  css  js  c++  java
  • BZOJ 1070 修车

    题意:

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

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

    分析:

      (个人认为这题如果改成个第三代排队接水之类的,得有好多人拿贪心做)

      这题就是一个排队在一个水龙头接水问题的强化再强化版。

      一如既往,我们要知道一些人在维修的时候,其他人也是在等着的。

      我们用的是最暴力的建图方式,即使这样我们还是可以体会到它的巧妙。

      源点向每辆车连流量1费用0的边。

      我们把每个工人拆成n个点,每人的第i号点表示这位师傅修的第n-i+1辆车(不是他修第n-i+1辆,是他一个人所修的第n-i辆(他已经修了n-i辆了))

      之后我们将N辆车的点和这N*M个点都连起来,流量为1,费用为这位师傅的这个点的编号与他修这辆车的时间的乘积。

      表示如果让这位师傅在修过n-i辆车之后再修这辆车,为所有人带来的时间代价是多少。

      可以这样理解,如果一辆车连某个工人的第n号点,代表它是这个工人修的第一辆车,而且其他车都在这个工人排队(就是说这个工人一共要修掉n辆车)所以产生的时间代价是(n*这辆车的代价),因为一共是n个人在等。

      然后别忘了输出最小费用除以N的值。

    代码:

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 const int inf=0x3f3f3f3f;
     8 const int N=100005;bool vis[N];
     9 struct node{int y,z,f,nxt;}e[N];
    10 int d[N],pre[N],f[N],lst[N],h[N];
    11 int n,m,c=1,ans,S,T,b[1001][1001];
    12 void add(int x,int y,int f,int z){
    13     e[++c]=(node){y,z,f,h[x]};h[x]=c;
    14     e[++c]=(node){x,-z,0,h[y]};h[y]=c;
    15 } queue<int>q;
    16 bool spfa(){
    17     for(int i=S;i<=T;i++)
    18     vis[i]=false,pre[i]=-1,
    19     lst[i]=0,d[i]=inf,f[i]=inf;
    20     q.push(S);d[S]=0;vis[S]=1;pre[S]=0;
    21     while(q.size()){
    22         int x=q.front();q.pop();vis[x]=0;
    23         for(int i=h[x],y;~i;i=e[i].nxt)
    24         if(d[y=e[i].y]>d[x]+e[i].z&&e[i].f){
    25             d[y]=d[x]+e[i].z;
    26             pre[y]=x;lst[y]=i;
    27             f[y]=min(f[x],e[i].f);
    28             if(!vis[y])vis[y]=1,q.push(y);
    29         }
    30     } return (pre[T]!=-1);
    31 } int main(){
    32     scanf("%d%d",&m,&n);T=n*m+n+1;
    33     for(int i=S;i<=T;i++) h[i]=-1;
    34     for(int k=1;k<=n;k++)
    35     add(S,m*n+k,1,0);
    36     for(int k=1;k<=n;k++)
    37     for(int i=1;i<=m;i++)
    38     scanf("%d",&b[i][k]);
    39     for(int i=1;i<=m;i++)
    40     for(int j=1;j<=n;j++){
    41         int x=(i-1)*n+j;
    42         for(int k=1;k<=n;k++)
    43         add(n*m+k,x,1,j*b[i][k]);
    44         add(x,T,1,0);
    45     } while(spfa()){
    46         ans+=f[T]*d[T];int x=T;
    47         while(x) e[lst[x]].f-=f[T],
    48         e[lst[x]^1].f+=f[T],x=pre[x];
    49     } printf("%.2f",ans/(n*1.0));
    50 }
    最小费用最大流

      

  • 相关阅读:
    函数 20140829
    结构体 20140827
    经典小游戏--推箱子
    更改版本与集合 20140826
    冒泡排序 20140823
    数组 20140822
    语句与字符串的属性及方法 20140820
    20141021WinForm控件属性
    20141014C#面向对象抽象方法,抽象类,接口
    20141011C#面向对象基础
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10250630.html
Copyright © 2011-2022 走看看