1. 程式人生 > >P1031 均分紙牌——————貪心

P1031 均分紙牌——————貪心

P1031 均分紙牌

題目描述

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

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

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

例如N=4 4堆紙牌數分別為:

①9②8③17④6
移動3次可達到目的:

從 ③ 取4張牌放到 ④ (9,8,13,10)-> 從 ③ 取33張牌放到 ②(9,11,10,10)-> 從 ② 取1張牌放到①(10,10,10,10)。

輸入格式:

兩行

第一行為:NN(NN 堆紙牌,1 \le N \le 1001≤N≤100)

第二行為: A 1 , A 2 ,

, A n A_1,A_2, … ,A_n (N堆紙牌,每堆紙牌初始數, 1
A i 10000 1 \le A_i \le 10000
)

輸出格式:

一行:即所有堆均達到相等時的最少移動次數。

輸入輸出樣例
輸入樣例
4
9 8 17 6

輸出樣例
3


先找出來紙牌數量的平均值ave,
然後對於每一對紙牌都讓其減去這個平均值
所以我們得到的結果就是,如果紙牌個數大於平均值,那麼它就大於0,小於平均值,它就小於0

這樣一來我們可以得出這樣的策略:從左到右開始找,如果第i堆紙牌的個數 a i a_i 不等於0,那麼移動次數就+1, a i + 1    + =    a i a_{i+1}\; += \;a_i ,一直處理到最後一個就行,應為題目保證紙牌總數必為N的倍數,所以不用擔心陣列越界

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,ave;
    int a[108];
    cin>>n;
    for(int i=0;i<n;++i)
        cin>>a[i], ave+=a[i];
    ave/=n;
    for(int i=0;i<n;++i)    a[i]-=ave;
    int ans = 0;
    for(int i=0;i<n;++i)
    {
        if(!a[i])       continue;
        a[i+1]+=a[i];
        ans++;
    }
    cout<<ans<<endl;
    return 0;
}