山區建小學

山區建小學

題目鏈接:luogu P4677luogu\ P4677

題目

政府在某山區修建了一條道路,恰好穿越總共nn個村莊的每個村莊一次,沒有迴路或交叉,任意兩個村莊只能通過這條路來往。已知任意兩個相鄰的村莊之間的距離爲did_i(爲正整數),其中,0<i<n0<i<n。爲了提高山區的文化素質,政府又決定從nn個村中選擇mm個村建小學。請根據給定的nnmm以及所有相鄰村莊的距離,選擇在哪些村莊建小學,才使得所有村到最近小學的距離總和最小,計算最小值。

輸入

11行爲nnmm,其間用空格間隔。

第2行爲n1n-1個整數,依次表示從一端到另一端的相鄰村莊的距離,整數之間以空格間隔。

例如:

10 310\ 3
2 4 6 5 2 4 3 1 32\ 4\ 6\ 5\ 2\ 4\ 3\ 1\ 3

表示在1010個村莊中建33所學校。第11個村莊與第22個村莊距離爲22,第22個村莊與第33個村莊距離爲44,第33個村莊與第44個村莊距離爲66......,第99個村莊到第1010個村莊的距離爲33

輸出

各村莊到最近學校的距離之和的最小值。

樣例輸入

10 2
3 1 3 1 1 1 1 1 3

樣例輸出

18

數據範圍

0 < m <= n < 5000\ <\ m\ <=\ n\ <\ 500

0 < di <= 1000\ <\ d_i\ <=\ 100

思路

這道題是一道動態規劃。

要做出這道題,最重要的一部是怎麼求出iijj第之間的所有村莊都到一個學校時,所需要的距離總和的最小值。
那麼在這裏呢,我們就認爲最中間的村莊就是可以讓距離總和最小的。我們用f[i][j]f[i][j]表示,在第ii個村莊到第jj個村莊中只建一個學校所能獲得的最小距離總和。那麼我們就可以通過前綴和和我們的貪心求出ff

接着呢,我們就可以通過dpdp求出答案。至於怎麼dpdp呢,很簡單,就是這個:
f[i][j] = min(f[i][j], f[k][j  1] + dis[k + 1][i]) j  1 <= k <= if[i][j]\ =\ min(f[i][j],\ f[k][j\ -\ 1]\ +\ dis[k\ +\ 1][i])\ (j\ -\ 1\ <=\ k\ <=\ i)
其中,disdis表示我們之前算出來的距離,而kk就表示分界點。
這個其實就是一個FloyedWarshallFloyed-Warshall算法,只是表示的方法不一樣,而且因爲nn最大隻有500500,所以三重循環是可行的。

代碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

int n, m, a[501], dis[501][501], f[501][501];

int main() {
	scanf("%d %d", &n, &m);//讀入
	for (int i = 2; i <= n; i++) {
		scanf("%d", &a[i]);//讀入
		a[i] += a[i - 1];//前綴和
	}
	
	for (int i = 1; i <= n; i++)
		for (int j = i; j <= n; j++) {
			int school = (i + j) >> 1;//應該建的位置
			for (int k = i; k <= j; k++)
				dis[i][j] += abs(a[school] - a[k]);//求出距離
		}
	
	memset(f, 0x7f, sizeof(f));//初始化
	f[0][0] = 0;//初始化
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			if (j > i) {
				f[i][j] = 0;//每個地方都可以建學校
				continue;
			}
			for (int k = j - 1; k <= i; k++)
				f[i][j] = min(f[i][j], f[k][j - 1] + dis[k + 1][i]);//動態轉移方程
		}
	
	printf("%d", f[n][m]);//輸出
	
	return 0;
}

You cant see me.{\color{white} You\ can't\ see\ me.}  You cant see me{\color{white}\ \ You\ can't\ see\ me}
You cant see me.{\color{white} You\ can't\ see\ me.}  You cant see me{\color{white}\ \ You\ can't\ see\ me}
You cant see me.{\color{white} You\ can't\ see\ me.}  You cant see me{\color{white}\ \ You\ can't\ see\ me}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章