標籤:des style blog http color 使用
Problem Description
有非常多從磁碟讀取資料的需求,包含順序讀取、隨機讀取。為了提高效率,須要人為安排磁碟讀取。然而,在現實中,這樣的做法非常複雜。我們考慮一個相對簡單的情境。磁碟有很多軌道,每一個軌道有很多扇區,用於儲存資料。當我們想在特定扇區來讀取資料時,磁頭須要跳轉到特定的軌道、詳細扇區進行讀取操作。為了簡單,我們如果磁頭能夠在某個軌道順時針或逆時針勻速旋轉,旋轉一周的時間是360個單位時間。磁頭也能夠任意移動到某個軌道進行讀取,每跳轉到一個相鄰軌道的時間為400個單位時間,跳轉前後磁頭所在扇區位置不變。一次讀取資料的時間為10個單位時間,讀取前後磁頭所在的扇區位置不變。磁頭同一時候僅僅能做一件事:跳轉軌道,旋轉或讀取。如今,須要在磁碟讀取一組資料,如果每一個軌道至多有一個讀取請求,這個讀取的扇區是軌道上分布在 0到359內的一個整數點扇區,即軌道的某個360等分點。磁頭的起始點在0軌道0扇區,此時沒有資料讀取。在完畢全部讀取後,磁頭須要回到0軌道0扇區的始點位置。請問完畢給定的讀取所需的最小時間。
Input
輸入的第一行包括一個整數M(0<M<=100),表示測試資料的組數。對於每組測試資料,第一行包括一個整數N(0<N<=1000),表示要讀取的資料的數量。之後每行包括兩個整數T和S(0<T<=1000,0<= S<360),表示每一個資料的磁軌和扇區,磁軌是按升序排列,而且沒有反覆。
Output
對於每組測試資料,輸出一個整數,表示完畢所有讀取所需的時間。
Sample Input
311 1031 203 305 1021 102 11
Sample Output
83040901642
本題是本次題目中最難的題目了,由於通過的人數最小,不斷有人覺得自己的程式正確而無法通過。
大概非常多人都使用了簡單的暴力法去解決這道題目,而這是個錯誤的方法,當然WA啦。
正確的解法應該是bitonic TSP - 能夠參考<Introduction to Algorithm>第15章的練習題。
由於題目限定了每一個資料都須要訪問一次,並且是須要從出發點出發,最後回到出發點的,形成完美符合Bitonic TSP的問題。
如的b圖就是Bitonic TSP的路線,a是最優路線,可是這裡的問題限定了並不須要TSP的最優路線。
發散思考:
1 並非類比讀資料的方式從開始出發讀資料,然後再往回讀,而是想象有兩個讀資料的磁頭,一直讀到結尾點,兩磁頭重合。
2 讀資料的時間另外計算:N * 10(N個資料,每一個資料須要10個單位時間。
#include <stdio.h>#include <cmath>#include <stdlib.h>#include <vector>using namespace std;class DiskSchedule_3{struct TS{int T, S;};int getDist(vector<TS> &gra, int i, int k){int d = (gra[k].T-gra[i].T) * 400;if (abs(gra[k].S-gra[i].S) <= 180) d += abs(gra[k].S-gra[i].S);else d += 360 - abs(gra[k].S-gra[i].S);return d;}public:DiskSchedule_3(){int M, N;scanf("%d", &M);while (M--){scanf("%d", &N);vector<TS> gra(N+1);for (int i = 1; i <= N; i++){scanf("%d %d", &gra[i].T, &gra[i].S);}vector<vector<int> > tbl(N+1, vector<int>(N+1));for (int i = 1; i <= N; i++){for (int k = 0; k <= i; k++){if (k+1 < i) tbl[k][i] = tbl[k][i-1] + getDist(gra, i-1, i);else{tbl[k][i] = tbl[0][k] + getDist(gra, 0, i);for (int r = 1; r < i; r++){int d = tbl[r][k] + getDist(gra, r, i);tbl[k][i] = min(tbl[k][i], d);}}}}printf("%d\n", tbl[N][N] + 10 * N);}}};