【BZOJ1070】[SCOI2007]修車
阿新 • • 發佈:2019-01-19
最小 print ext add 就是 時間 line next 人在
表示“把第i輛車讓第j個人在“需要消耗k次時間”的那個個位置修”
那實際上我們就是對於每個\(i\)選取一個這樣的決策,同時這個決策的\(\left(j,k\right)\)不能相同
最後怎麽辦呢?
建一個\(n*m\)的決策圖,表示決策\(j,k\)
再建\(n\)個車的點,表示那輛車
再對於決策圖的每一層,向車\(i\)連\(Ti,j*層數\)費用,容量為\(1\)的邊
最後連\(S,T\)即可
代碼
【BZOJ1070】[SCOI2007]修車
題面
以後要多寫題面flag
題目描述
同一時刻有\(N\)位車主帶著他們的愛車來到了汽車維修中心。維修中心共有\(M\)位技術人員,不同的技術人員對不同的車進行維修所用的時間是不同的。現在需要安排這M位技術人員所維修的車及順序,使得顧客平均等待的時間最小。
說明:顧客的等待時間是指從他把車送至維修中心到維修完畢所用的時間。
輸入格式
第一行有兩個數\(M,N\),表示技術人員數與顧客數。
接下來\(n\)行,每行\(m\)個整數。第\(i+1\)行第\(j\)個數表示第\(j\)位技術人員維修第\(i\)輛車需要用的時間T。
輸出格式
最小平均等待時間,答案精確到小數點後2位。
樣例
輸入樣例
2 2
3 2
1 4
輸出樣例
1.50
說明
\((2\leq M\leq 9,1\leq N\leq 60), (1\leq T\leq 1000)\)
題解
設某個技術人員的修車序列為\(a_1,a_2...a_n\)
則這個人所用時間
\[
\sum_{i=1}^nT_{a_i}*(n-i+1)\\Leftrightarrow n*T_{a_1}+(n-1)*T_{a_2}+...+1*T_{a_n}
\]
這樣的話,我們可以將一次在第\(k\)次修決策化為一次
費用為\(T_{i,j}*k\)的決策
因此我們可以得到一個決策集合:決策\(\left(i,j,k\right)=T\left(i,j\right)\ast k\)
那實際上我們就是對於每個\(i\)選取一個這樣的決策,同時這個決策的\(\left(j,k\right)\)不能相同
最後怎麽辦呢?
建一個\(n*m\)的決策圖,表示決策\(j,k\)
再建\(n\)個車的點,表示那輛車
再對於決策圖的每一層,向車\(i\)連\(Ti,j*層數\)費用,容量為\(1\)的邊
最後連\(S,T\)即可
代碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; const int MAX_N = 300; const int INF = 1e9; struct Graph { int to, cap, cost, next; } e[MAX_N * MAX_N << 2]; int fir[MAX_N * MAX_N], e_cnt, V; void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; } void Add_Edge(int u, int v, int cap, int cost) { e[e_cnt] = (Graph){v, cap, cost, fir[u]}; fir[u] = e_cnt++; e[e_cnt] = (Graph){u, 0, -cost, fir[v]}; fir[v] = e_cnt++; } int dis[MAX_N * MAX_N], preve[MAX_N * MAX_N], prevv[MAX_N * MAX_N]; bool inq[MAX_N * MAX_N]; int min_cost_flow(int s, int t) { static queue<int> que; int res = 0; while (1) { fill(&dis[0], &dis[V + 1], INF); fill(&inq[0], &inq[V + 1], 0); que.push(s), dis[s] = 0, inq[s] = 1; while (!que.empty()) { int x = que.front(); que.pop(); for (int i = fir[x]; ~i; i = e[i].next) { int v = e[i].to; if (dis[x] + e[i].cost < dis[v] && e[i].cap > 0) { dis[v] = dis[x] + e[i].cost; preve[v] = i, prevv[v] = x; if (!inq[v]) que.push(v), inq[v] = 1; } } inq[x] = 0; } if (dis[t] == INF) return res; int d = INF; for (int x = t; x != s; x = prevv[x]) d = min(d, e[preve[x]].cap); res += dis[t] * d; for (int x = t; x != s; x = prevv[x]) { e[preve[x]].cap -= d; e[preve[x] ^ 1].cap += d; } } } int N, M, id[MAX_N][MAX_N], T[MAX_N][MAX_N]; int main () { clearGraph(); cin >> M >> N; int s = 0, t, tot = 0; for (int i = 1; i <= N; i++) for (int j = 1; j <= M; j++) id[i][j] = ++tot; for (int i = 1; i <= N; i++) for (int j = 1; j <= M; j++) cin >> T[i][j]; V = t = (N + 1) * M + 1; for (int i = 1; i <= N; i++) Add_Edge(s, i, 1, 0); for (int i = 1; i <= N; i++) for (int j = 1; j <= M; j++) Add_Edge(N + id[i][j], t, 1, 0); for (int i = 1; i <= N; i++) for (int j = 1; j <= M; j++) for (int k = 1; k <= N; k++) Add_Edge(i, N + id[k][j], 1, T[i][j] * k); printf("%0.2lf\n", 1.0 * min_cost_flow(s, t) / N); return 0; }
【BZOJ1070】[SCOI2007]修車