**在某山區修建了一條道路,恰好穿越總共m個村莊的每個村莊一次,沒有迴路或交叉,任意兩個村莊只能通過這條路來往。已知任意兩個相鄰的村莊之間的距離為di(為正整數),其中,0 < i < m。為了提高山區的文化素質,**又決定從m個村中選擇n個村建小學(設 0 < n < = m < 500 )。請根據給定的m、n以及所有相鄰村莊的距離,選擇在哪些村莊建小學,才使得所有村到最近小學的距離總和最小,計算最小值。
第1行為m和n,其間用空格間隔
第2行為(m-1) 個整數,依次表示從一端到另一端的相鄰村莊的距離,整數之間以空格間隔。
例如10 3
2 4 6 5 2 4 3 1 3
表示在10個村莊建3所學校。第1個村莊與第2個村莊距離為2,第2個村莊與第3個村莊距離為4,第3個村莊與第4個村莊距離為6,…,第9個村莊到第10個村莊的距離為3。
各村莊到最近學校的距離之和的最小值。
10 2
3 1 3 1 1 1 1 1 3
18**
元培-from whf
動態規劃來解決,這裡需要乙個輔助的陣列dist,dist[i][j]表示在從i到j這一段區間建一所小學,i到j的村莊都到這個學校來上學的路程和。
狀態表達:f[i][j]表示前i個村莊建j所學校,到裡那個村莊最近的學校上學的路程和。
狀態轉移:f[i][j] = std::min(f[i][j],f[k][j-1]+dist[k+1][i]),也就是:
for(int i = 1;i<=n;i++)
for(int j = 1;j狀態數量:n^2
轉移代價:o(n)
時間複雜度:o(n^3)
空間複雜度:o(n^2)
還有乙個關鍵點,就是有關如何求dist陣列的,其實,我們可以發現,在i到j村莊裡建小學,選i到j村莊的路程的中間位置村莊,一定是最優的。畫個圖你就能發現了。
如何快速求dist呢,其實,dist[i][j]等於dist[i][j-1]+num[j]-num[i+j]/2的,建議畫個圖。
#include#include#include#include#includeint num[1001],dist[1001][1001],f[1001][1001];
int main()
for(int i = 1;i<=n;i++)
for(int j = i;j<=n;j++)
dist[i][j] = dist[i][j-1]+num[j]-num[(i+j)/2];
memset(f,0x3f,sizeof(f));
for(int i = 1;i<=n;i++)f[i][1] = dist[1][i];
for(int i = 1;i<=n;i++)
for(int j = 1;jfor(int k = 1;kf[i][j] = std::min(f[i][j],f[k][j-1]+dist[k+1][i]);
std::cout
}
openjudge7624 山區建小學
描述 在某山區修建了一條道路,恰好穿越總共m個村莊的每個村莊一次,沒有迴路或交叉,任意兩個村莊只能通過這條路來往。已知任意兩個相鄰的村莊之間的距離為di 為正整數 其中,0 i m。為了提高山區的文化素質,又決定從m個村中選擇n個村建小學 設 0 n m 500 請根據給定的m n以及所有相鄰村莊的...
openjudge 數字統計
總時間限制 1000ms 記憶體限制 100000kb 描述輸入n個整數,統計每個數出現的次數.輸入 第一行是乙個整數n 1 n 1000 接下來n行每行乙個整數.輸出 第一行輸出總共有多少個不同的整數.接下來每行輸出乙個整數及這個整數出現的次數,用空格分隔.輸出的整數的順序與它們在輸入中第一次出現...
Openjudge 括號匹配
這個用了普通的迴圈,資料量不是很大的話效率還是不錯的,如果資料比較大的話,換別的方法可能效率會高一點。思路很簡單 以字串中是否還存在沒有匹配過的 作為這個字串已經處理完畢的標誌。1,讀入字串,並進行處理,把所有不是 和 的字元都轉換成空格。2,從開始掃瞄字串,如果掃瞄到 記錄 的位置,直到掃瞄到 3...