有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)
第二行為:(n堆紙牌,每堆紙牌初始數,1≤ai ≤10000)
一行:即所有堆均達到相等時的最少移動次數。
4——————————————————解題分割線————————————————————9 8 17 6
其實這道題有兩個地方是重點,乙個就是題中強調了每一堆(除了頭和尾)只可以向左堆或右堆移動紙牌,且每次移動紙牌的數量不限(這是關鍵)。還有乙個就是,題中特地強調了:紙牌總是必定是n的倍數。
那麼,很顯然,就可以求出最終每一堆的紙牌數應該是 each = total / n。
接下來就是如移動的問題,移動一定是要有秩序、有規律的移動,隨便亂移動一定不是最少的。
所以必須要找出乙個移動的起始點,而哪種堆必定是要移動的呢?
當然是初始紙牌數大於each的,而這些堆可能不止乙個,哪乙個是最適合定為起始點的呢?
那就是最多的那個紙牌堆。
找到最多的紙牌堆後,接下來就要移動紙牌了,對於乙個紙牌堆(假設紙牌堆在中間某處,在頭或尾就只要一邊討論),移動紙牌有兩個選擇:向左or向右,那麼各移動多少呢?自然可以想到,最多的那一堆所多出來紙牌數必定是他兩邊所缺的紙牌數之和,那麼就看兩邊各需要多少紙牌就各移動多少紙牌。
所以我們一開始的預處理和資料準備過程就要做到這幾個方面:1、計算出紙牌數的總和 total。2、找出紙牌數最多的那個堆,記錄下它的location。3、計算出最大紙牌數堆的左側紙牌數總和,進而求出左側需要的紙牌數(或多出的紙牌數)。
最終將移動的紙牌向兩邊分發,需要多少就給多少,多出多少就拿走多少,每出現一次這樣拿或給的情況,結果就++。
還是上**吧。
#include
using
namespace std;
int n,a[
105]
,maxx=-1
;int
main()
total +
= a[i];}
int each = total / n;
//最終實現情況
int left_need =
(each *
(loc -1)
)- left_total;
// 變數為正數即是左邊缺,為負數就是左邊富餘,缺就給,富餘就拿,同樣都需要一步來完成
int right_need = a[loc]
- left_need - each;
//右邊同理
int k = loc -1;
int ans =0;
//對左邊進行處理
while
(k >=1)
else
k--;}
k = loc+1;
//對右邊進行處理
洛谷 P1031 均分紙牌
p1031 均分紙牌 這道題告訴我們,對於實在想不出演算法的題,可以大膽按照直覺用貪心,而且在考試中永遠不要試著去證明貪心演算法,因為非常難證,會浪費大量時間。這就是你們都不去證的理由?這道題貪心演算法就是,計算牌的平均數,然後除了最後一堆以外,每堆都通過把多餘牌移到下一堆或從下一堆取牌來使其達到平...
洛谷 P1031均分紙牌
恰似又更了四章 我現在只能期待他不在什麼工作日突然來乙個十篇得大爆更了 我現在要更一篇水題了 希望不會被不小心看到的大佬們嫌棄 題目描述 有n堆紙牌,編號分別為 1,2,n。每堆上有若干張,但紙牌總數必為n的倍數。可以在任一堆上取若干張紙牌,然後移動。移牌規則為 在編號為1堆上取的紙牌,只能移到編號...
洛谷P1031 均分紙牌
題目鏈結 均分紙牌 解題思路 貪心演算法,最簡單的模擬 最壞的情況就是移動n 1次 如果紙牌本來就滿足條件就不需要再移動 預處理就是求每堆紙牌與平均數的關係,多1記為1,少1記為 1 從左至右依次掃瞄,a i 0的就把多的部分給右邊那堆,a i 0的就從右邊那堆拿過來補上 附上 include us...