2-10. 海盗分赃
P个海盗偷了D颗钻石后来到公海分赃,一致同意如下分赃策略:
首先,P个海盗通过抽签决定1-P的序号。然后由第1号海盗提出一个分配方案(方案应给出每个海盗分得的具体数量),如果能够得到包括1号在内的绝对多数(即大于半数)同意,则按照该分配方案执行,否则1号将被投入大海喂鲨鱼;而后依次类似地由第2号、第3号等等海盗提出方案,直到能够获得绝对多数同意的方案出现为止,或者只剩下最后一位海盗,其独占所有钻石。请编写一个程序,给出第1号海盗的钻石分配方案中自己分得的钻石数量。
附带的三个假定:
1) “聪明”与“贪婪”假定:每个海盗总能够以本人利益最大化作为行为准则;
2) “人性化”假定:在能够取得尽量多钻石的情况下,海盗不会故意致同伙于死地;
3) “无偏见”假定:海盗之间没有个人恩怨,分给其他海盗钻石的次序以小序号优先为原则。
输入格式说明:
输入2个正整数D和P(3<=P<=D<=100)。
输出格式说明:
输出第1号海盗的钻石分配方案中自己分得的钻石数量。
样例输入与输出:
序号 | 输入 | 输出 |
1 | 10 7 | 6 |
2 | 3 3 | 2 |
3 | 100 3 | 99 |
4 | 100 100 | 49 |
//大家可能看过经典的海盗分账问题,这题有点区别,因为他给了一些限制,看题目给的第三个案例,当输入为100 3时,输出为99. 可以想到的分配方式为99 1 0。我们理一下思路。如果倒数第四个人想获得最多的钻石而且获得半数以为上的票,他就应该给倒数第一和倒数第二个人2和1个钻石,因为倒数第三个人不管怎么样都会投出反对票,所以不用给他钻石,因为只要倒数第一和倒数第二人投他就行了,所以分配结果为97 0 2 1。依次类推,倒数第五个人也想到这点 ,所以他不会给倒数第四个人钻石,而他只要给倒数第三个人一个钻石就可以了,现在还差一票,所以只要给倒数第一个人2颗钻石他就会乖乖的投你一票,而倒数第二个就不要给他钻石了,得到分配方式97 0 1 0 2.再依次类推,你会发现,在倒数第n人分配的时候,倒数第n-1个人一定会反对,所以倒数第n个人想要获得半数以上的票,就要把希望寄托在倒数第1~(n-2)这 n-2个人身上。所以只要给其中(n-2)/2+1个人的钻石数比第n-1个人给他们的要多一个,他们就会支持你。所以算法可以对后面的n-2个人进行排序,并挑取钻石数最少的(n-2)/2+1个人,多给他们一个钻石,而对于其他的人,直接不给钻石。。这样就ok了。
#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;
deque<int> de;
int main()
{
int D, P;
cin>>D>>P;
de.push_back(0);
de.push_back(1);
de.push_back(D-1);
int i;
for(i = 3; i < P; ++i)
{
sort(de.begin(), de.end());
int j, sum = 0;
for (j = 0; j < de.size(); ++j)
{
if(j < (de.size()-1)/2+1)
{
de[j] ++;
sum += de[j];
}
else
de[j] = 0;
}
de.push_back(D-sum);
}
cout<<de[P-1]<<endl;
return 0;
}