說難就難的貪心(一) 均分紙牌問題

2021-08-07 02:56:59 字數 1252 閱讀 4278

有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的倍數,且需每堆牌數相等,所以我們可以使用「平均數」這個神奇的東西。

我們可以預處理一下:

step 1:算出平均數;

step 2:for迴圈減去平均數。

我們就可以把每堆牌記為與平均數相差n,0就表示該堆牌已完成移動,不為零則還缺或者多n張牌。

但我們需要注意的是:如果記為0的牌堆在中間的話,這種牌堆就不能忽略掉(原因請讀者自己去想)

其實很簡單,來一組資料就知道了:

5

5 3 1 5 11

預處理之後:

0 -2 -4 0 6

如果你忽略掉0的話,你的程式就會輸出:

顯然是錯的,所以中間的0不可忽略!!!

做到上面幾點之後,我們就可以朝著乙個方向移動,即可貪心。

此題**較為簡單,但需注意移動時記次數的方法。

(**請讀者自行研究)

#include

int n,a[105],s,tot;

int main()

s/=n;

for(int i=1;i<=n;i++)//預處理

a[i]-=s;

for(int i=2;i<=n;i++)

if(a[i-1]!=0)

printf("%d",tot);

return

0;}

p.s.我在這裡不能保證此**正確性

小白創業,難就難在從0到1的過程。

小白創業,難就難在從0到1的過程。沒有誰生來就什麼都會,只是有的人經歷的多,有的人經歷相對較少!所以,最近幾年出現了很多創業的社群和很多只是付費的專案。只是,所謂的創業社群,和講課的熱,有很多是自己本身沒做什麼專案的?他們的專案就是紙上談兵。紙上談兵就是他們的專案。如果你做過網際網路專案,你會覺得公...

貪心演算法並不難,難的是證明。

貪心算 法並不難 難的是 證明 貪心演算法並不難,難的是證明。貪心演算法並不 難,難的 是證明。heidoudou 基本思路 先將陣列sor tsort sort 一遍,然後用雙指標i 1,j n,if ai a j w if a i a j w if ai aj w 則將a ja j aj 單獨分...

c 程式設計練習 002 難一點的swap

填空,使得程式輸出結果是 5,3 include using namespace std void swap intmain 輸入無輸出 5,3樣例輸入 無樣例輸出 5,3 guo wei 此處如果單純的只傳入void swap int a,int b 那麼我們會發現其實兩個值在輸出時,並沒有發生交...