1. 程式人生 > >[SCOI2007]修車

[SCOI2007]修車

printf tput getch input http 答案 void 表示 ()

1070: [SCOI2007]修車

Time Limit: 1 Sec Memory Limit: 128 MB Submit: 6007 Solved: 2559 [Submit][Status][Discuss]

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)

對於每個維修師傅拆成$n$個點,每個點在連邊時費用對應乘上相應的倍數,因為如果一個維修師傅修多個車的話等待時間需要乘上一定倍數。然後跑最小費用最大流

#include <cstdio>
inline int readint(){
    int f = 1, n = 0;
    char ch = getchar();
    
while(ch < 0 || ch > 9){ if(ch == -) f = -1; ch = getchar(); } while(ch <= 9 && ch >= 0){ n = (n << 1) + (n << 3) + ch - 0; ch = getchar(); } return f * n; } const int maxn = 100, maxm = 15, INF = 0x3f3f3f3f; struct
Edge{ int to, cap, cost, next; Edge(){} Edge(int _t, int _w, int _c, int _n): to(_t), cap(_w), cost(_c), next(_n){} }e[maxn + maxn * maxn * maxm + maxn * maxm << 1]; int fir[maxn + maxn * maxm] = {0}, cnt = 1; inline void ins(int u, int v, int w, int c){ e[++cnt] = Edge(v, w, c, fir[u]); fir[u] = cnt; e[++cnt] = Edge(u, 0, -c, fir[v]); fir[v] = cnt; } int sour, sink; bool inq[maxn + maxn * maxm] = {false}; int dis[maxn + maxn * maxm]; int q[maxn + maxn * maxm], head, tail; int pre[maxn + maxn * maxm]; bool SPFA(){ for(int i = sour; i <= sink; i++){ dis[i] = INF; inq[i] = false; pre[i] = 0; } head = tail = 0; dis[sour] = 0; inq[sour] = true; q[tail++] = sour; int u, v; while(head != tail){ u = q[head++]; if(head == 1600) head = 0; inq[u] = false; for(int i = fir[u]; i; i = e[i].next){ v = e[i].to; if(e[i].cap && dis[v] > dis[u] + e[i].cost){ dis[v] = dis[u] + e[i].cost; pre[v] = i; if(!inq[v]){ inq[v] = true; q[tail++] = v; if(tail == 1600) tail = 0; } } } } return dis[sink] != INF; } int MCMF(){ int flow, cost = 0; while(SPFA()){ flow = INF; for(int i = pre[sink]; i; i = pre[e[i ^ 1].to]) if(e[i].cap < flow) flow = e[i].cap; for(int i = pre[sink]; i; i = pre[e[i ^ 1].to]){ e[i].cap -= flow; e[i ^ 1].cap += flow; } cost += flow * dis[sink]; } return cost; } int main(){ int m, n; m = readint(); n = readint(); sour = 0; sink = n + n * m + 1; for(int i = 1; i <= n; i++) ins(sour, i, 1, 0); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){ int t = readint(); for(int k = 1; k <= n; k++) ins(i, j * n + k, 1, k * t); } for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) ins(i * n + j, sink, 1, 0); printf("%.2lf\n", MCMF() * 1.0 / n); return 0; }

[SCOI2007]修車