快轉到主要內容

CSES-1074 Stick Lengths

目錄


題目連結:https://cses.fi/problemset/task/1074

題意
#

這題給定 \( n \) 根長度不同的木棍,目標是將它們修改為相同長度。
你可以任意把每一根木棍切短或接長,每改變 \( 1 \) 單位的長度就會消耗 \( 1 \) 的成本。
我們需要求出達成目標的最小總花費。

思路
#

要讓所有數字變成某個目標值,並使「差值的絕對值」總和最小,目標點應為這群數字的「中位數」。

平均數是讓「差值的平方和」最小的基準點。若將木棍長度視為數線上的點,
只有目標長度停留在中位數時,左右兩側的木棍數量才會大致平衡,使總距離和最小。

在實作上,先對所有長度進行排序以找出中位數,
再計算每根木棍和中位數的長度差並將其加總。
如果 \( n \) 是偶數,選擇中間兩個數字的任何一個作為目標均可。

程式碼
#

#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define fi first
#define se second
#define INF LONG_LONG_MAX/1000
#define WA() cin.tie(0)->sync_with_stdio(0)
#define all(x) (x).begin(), (x).end()
#define int long long
#define PII pair<int, int>

signed main() { WA();
    int n; cin >> n;
    vector<int> v(n);
    // 讀入所有木棍長度後,直接進行排序
    for (auto &i : v) cin >> i; sort(all(v));
    
    int k, sum = 0;
    // 根據總數是奇數還偶數,找出中位數 k
    if (n&1) k = v[n/2];
    else k = v[n/2-1];
    
    // 計算所有木棍與中位數的距離差總和
    for (auto &i : v) sum += abs(i-k);
    
    cout << sum << '\n';
}
Piau 的筆記本
作者
Piau 的筆記本
希望我寫下來的東西能夠長久的記在我的腦中