題目描述:
在一條數軸上有 n 家商店,它們的座標分別為 a1~an。現在需要在數軸上建立一家貨倉,每天清晨,從貨倉到每家商店都要運送一車商品。為了提高效率,求把貨倉建在何處,可以使得貨倉到每家商店的距離之和最小。
輸入格式
第一行輸入整數n。第二行n個整數a1~an。
輸出格式
輸出乙個整數,表示距離之和的最小值。
資料範圍
1≤n≤100000
輸入樣例:
4
6 2 9 1
輸出樣例:
12
分析:
題目是在數軸上求乙個點,使其到所有商店距離之和最小。我們設這點在x處,x的左邊有a個商店,右邊有b個商店。可以很輕鬆的得到,當a < b時,我們把x往右移動乙個很小的單位,則x的左邊距離之和增加了a,右邊的距離之和減少了b,總體來說距離之和就減少了b - a。這樣不斷的往右移動,直至x左右兩邊的商店數一樣多時就達到了最優解。
此時我們對商店數n分奇偶數討論,n為奇數,比如n = 9,我們把貨倉設在第五個點處,貨倉左邊右邊都是4個商店,就滿足了中位數的條件;n為偶數時,比如n = 10,是不是只有把貨倉設定在5-6的中點才能達到最優解呢?並不是,此時貨倉選在5-6之間任意一點都可以。
也可以採取另一種更精確的推導方式。距離之和s = |a1 - x| + |a2 - x| + ... +|an - x| = (|a1 - x| + |an - x|) + ...。即將a1,an作為一組,a2,an-1作為一組...。如果x在a1左邊,則|a1 - x| + |an - x| = a1 + an - 2x,如果x在an右邊,則|a1 - x| + |an - x| = 2x - a1 - an;x在a1與an之間時,|a1 - x| + |an - x| = x - a1 + an - x = an - a1。更直觀的圖形表示是:
x在a1左邊或者在an右邊時,x到a1和an的距離之和要大於a1到an的距離,而x在a1到an之間時,x到a1和an的距離之和等於a1到an的距離,所以對於任意一對點,x在兩點之間時距離之和最小。如果一共有偶數個點,x位於最中間兩個點之間,則可以使得距離之和s中任意一組(|ai - x| + |aj - x|)均最小,故s最小;奇數個點時,x取最中間的那個點,同樣其它的各組距離和最小,總的s也最小。
具體程式設計時,首先對陣列進行排序,方便尋找中位數。我們不用向上面那樣分奇偶數討論,比如a,b,c三點,貨倉在b點,a,c到b的距離之和就是c-a;(假設a < b < c),就算非要逐步累加b - a + c - b = c - a,結果是一樣的。這就意味著貨倉我們選在中點,兩側成對出現的商店到貨倉距離之和就是二者座標之差,也就是a[n-1] - a[0],...舉個例子:n = 9,ans = a[8] - a[0] + a[7] - a[1] +... +a[4] - a[4](因為貨倉設在第四個點),n = 8時,最後就是a[4] - a[3]。
#include #include using namespace std;
typedef long long ll;
const int maxn = 100005;
int a[maxn];
int main()
AcWing 104 貨倉選址
在一條數軸上有 n 家商店,它們的座標分別為 a1 an。現在需要在數軸上建立一家貨倉,每天清晨,從貨倉到每家商店都要運送一車商品。為了提高效率,求把貨倉建在何處,可以使得貨倉到每家商店的距離之和最小。輸入格式 第一行輸入整數n。第二行n個整數a1 an。輸出格式 輸出乙個整數,表示距離之和的最小值...
AcWing 104 貨倉選址
在一條數軸上有 n 家商店,它們的座標分別為 a1 an。現在需要在數軸上建立一家貨倉,每天清晨,從貨倉到每家商店都要運送一車商品。為了提高效率,求把貨倉建在何處,可以使得貨倉到每家商店的距離之和最小。輸入格式 第一行輸入整數n。第二行n個整數a1 an。輸出格式 輸出乙個整數,表示距離之和的最小值...
ACWing 104 貨倉選址
在乙個數軸上有n nn家商店,座標分別是a1 na a1 n 需要在數軸上建立乙個倉庫,使得所有商店到這個倉庫的距離總和最小。問這個倉庫應該建在何處,返回最小的距離總和。輸入格式 第一行輸入整數n nn。第二行n nn個整數a1 an a 1 sim a n a1 an 輸出格式 輸出乙個整數,表示...