【題目描述】 有n堆紙牌,編號分別爲 1,2,…, 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; }