問題:圓桌旁坐著 n 個人,沒人有一定數量的金幣,金幣總數能被 n 整除。每個人可以給他左右相鄰的人一些金幣,最終使得每個人的金幣數目相等。要求求出被轉手的金幣數量的最小值 。比如:n=4,且4個人的金幣數量分別為1,2,5,4時,只需轉移4枚金幣(3給2兩枚,2和4分別給1一枚)即可實現每人手中的金幣數目相等。
要求:輸入包含多組資料。每組資料第一行為整數n(n<=1000000),以下 n 行每行為乙個整數,按逆時針順序給出每個人擁有的金幣數。輸入結束標誌為檔案結束符(eof)。輸出格式:對於每組資料,輸出被轉手金幣數量的最小值。
分析:首先,每個人最終擁有的金幣數目m是確定的,現在假設編號為 i 的人最初有 ai 枚金幣。對於1號來說,他給4號x1枚金幣,2號給他x2枚金幣,他最後還剩a1-x1+x2,於是,可得到方程a1-x1+x2=m。同理,對於第二個人,有a2-x2+x3=m, 直到,an-xn+x1=m。然後用x1表示出其他的xi,有x2=x1-c1(c1=a1-m),x3=x1-c2(c2=c1+a2-m),
.....現在要求xi的絕對值之和盡量小,即|x1|+|x1-c1|+|x1-c2|+|x1-c3|.....|x1-cn-1|要最小,由幾何意義可知,這實際上是求乙個最優x1使得其到ci 的距離最小。這一點實際上是這些數的中位數。
#include#includeusing
namespace
std;
const
int maxn=1000000+10
;long
long
a[maxn],c[maxn],tot,m;
intmain()
m=tot/n;
c[0]=0
;
for(int i=0;i)
c[i]=c[i-1]+a[i]-m;
sort(c,c+n);
long
long x1=c[n/2],ans=0
;
for(int i=0;i)
ans+=abs(x1-c[i]);
printf(
"%lld\n
",ans);
}return0;
}
海盜分金幣問題
另外乙個很有趣的問題 話說一天有5個海盜搶了一艘who的遊輪,搶到了100枚金幣,但這5個人沒有老大,不知道怎麼分這100枚金幣。不過5個人都絕頂聰明,他們決定 1,抽籤,決定12345五個號碼,2,由1號提分配方案,大家一起舉手表決,超過半數同意則通過 否則被扔進大海浬喂鯊魚 3,1號死了由2號提...
海盜分金幣的問題
數學的邏輯有時會導致看來十分怪異的結論。一般的規則是,如果邏輯推理沒有漏洞,那麼結論就必定站得住腳,即使它與你的直覺矛盾。1998年9月,加利福尼亞州帕洛阿爾托的stephen m.omohundro寄給我一道難題,它恰好就屬於這一類。這難題已經流傳了至少十年,但是omohundro對它作了改動,使...
海盜分金幣
首先,把這個問題轉換為乙個遞迴的演算法問題,描述為,如果我知道了上一家的分法,我如何能夠使我的利益最大化呢?現假定有5個人分,金幣總數是100,那麼第二個人的分法是1,1,0,98,那麼第乙個人需要的就是拉攏分的最少的兩人,然後給他們多乙個金幣,這樣就可以取得他們的支援了,所以第乙個人的分法是2,0...