1. 程式人生 > >洛谷P1368 均分紙牌(加強版)

洛谷P1368 均分紙牌(加強版)

hellip 問題 只有一個 一行 return ont -1 col 個數

P1368 均分紙牌(加強版)

題目描述

有 N 堆紙牌,編號分別為 1,2,…, N。每堆上有若幹張,紙牌總數必為 N 的倍數。可以在任一堆上取1張紙牌,然後移動。

移牌規則為:在編號為 1 堆上取的紙牌,能移到編號為 2和N 的堆上;在編號為 N 的堆上取的紙牌,能移到編號為 N-1和1 的堆上;其他堆上取的紙牌,可以移到相鄰左邊或右邊的堆上。

現在要求找出一種移動方法,使每堆上紙牌數都一樣多且牌的移動次數盡量少。

輸入輸出格式

輸入格式:

第一行一個整數n

第二行為n個空格分開的正整數,為n堆紙牌的牌數。

輸出格式:

只有一個數,為最少的移動次數。

輸入輸出樣例

輸入樣例#1:
4
1 2 5 4
輸出樣例#1:
4

說明

對樣例的說明:

①第4堆移動1張牌至第1堆

②第3堆移動1張牌至第2堆

③第3堆移動1張牌至第2堆

④第2堆移動1張牌至第1堆

此時移動次數為4最小

【數據範圍】

對於40%的數據,n<=10000

對於100%的數據,n<=1000000,所有紙牌數總和在2147483647內

/*
    設平均數為xba
    
    不妨設a1給了an x1 張紙牌(k可正可負),a2給了a1 x2張紙牌, a3給了a2 x3 張紙牌……an給了a(n - 1) xn張紙牌,不難發現以下方程:
    
    xba = a1 - x1 + x2
    xba = a2 - x2 + x3
    xba = a3 - x3 + x4
    xba = a4 - x4 + x5
    ......
    xba = a(n - 1) - x(n - 1) + xn
    xba = an - xn + x1
    
    我們考慮最終結果,應該是
    |x1| + |x2| + |x3| + .... + |xn|
    
    換元法,得到
    ans = |x1| + |xba - a1 + x1| + |2xba -a1 - a2 + x1| + |3xba -a1 - a2 - a3 + x1| + ..... + |(n - 1)xba - Σai,i <= n - 1|轉換為一次函數帶絕對值的最值問題
    
    數形結合思想,看做是數軸上點的距離。
    中位數時距離和最小。
*/ #include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define maxn 1000010 #define INF 0x3f3f3f3f long long a[maxn],sum,f[maxn],xba,n,k,ans; int main(){ scanf("%d",&n); for(long long i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } xba
=sum/n; f[1]=0; for(long long i=2;i<=n;i++) f[i]=f[i-1]+xba-a[i-1]; sort(f+1,f+n+1); k=f[n/2+1]; for(long long i=1;i<=n;i++) ans+=abs(k-f[i]); cout<<ans; return 0; }

洛谷P1368 均分紙牌(加強版)