均分紙牌(Noip2002)-貪心

【題目描述】
有n堆紙牌,編號分別爲 12,…, n。每堆上有若干張,但紙牌總數必爲n的倍數。能夠在任一堆上取若干張紙牌,而後移動。

移牌規則爲:在編號爲1的堆上取的紙牌,只能移到編號爲 2 的堆上;在編號爲 n 的堆上取的紙牌,只能移到編號爲n-1的堆上;其餘堆上取的紙牌,能夠移到相鄰左邊或右邊的堆上。

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

例如 n=4,4堆紙牌數分別爲:  ① 9 ② 8 ③ 17 ④ 6

移動3次可達到目的:

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


【輸入】
n(n 堆紙牌,1 ≤ n ≤ 100)

a1 a2 … an (n 堆紙牌,每堆紙牌初始數,l≤ ai ≤10000)。

【輸出】
全部堆均達到相等時的最少移動次數。

【輸入樣例】
4
9 8 17 6

【輸出樣例】 3

 題目意思是要以每次移動的牌數來達到平均數,也就是每堆牌把平均數當成目標去靠近;c++

貪心:一開始算出平均數,而後從左往右以這個平均數爲目標勻,因此可能只要勻一圈就能夠成功;spa

但若是一開始沒有貪心(沒有算出平均數),那麼從左到右勻了一遍後會發現沒有達到目的,會再從左到右勻一遍;code

因此一開始把目標選爲平均數就是貪心;那麼這樣的話只要勻一次,這樣每次勻牌的時候就等於在構造最優解,而後一遍下來就由局部最優達到了全局最優;blog

 一開始就算出平均數,每堆牌和平均數比較,用平均數減每堆的牌數,剩下的牌數就是離平均數的「距離」,而後從左往右勻=》無論這堆牌的正負,讓此堆牌加到下一堆牌,而後再讓此堆牌爲零;ci

 

樣例:it

(9+8+17+6)/4=10;class

對應貪心的牌數爲:-1;-2;7;-4;方法

第一次勻:0;-3;7;-4;移動

第二次:0;0;4;-4;di

第三次:0;0;0;0;

因此一共三次;

#include <bits/stdc++.h>

using namespace std;

int a[105];

int main()
{
    int n,i,avg,flag,s;
    avg=0;
    flag=0;
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
        avg=a[i]+avg;
    }
    s=avg/n;
    for(i=0;i<n;i++)
    {
        a[i]=a[i]-s;
    }
    for(i=0;i<n-1;i++)
    {
        if(a[i]!=0)  //若是等於0的話就不用管了;
        {
            a[i+1]=a[i]+a[i+1];
            a[i]=0;
            flag++;
        }
        else
            continue;
    }
    cout<<flag<<endl;
    return 0;
}
相關文章
相關標籤/搜索