PTA海盗分赃(25分)
P 个海盗偷了 D 颗钻石后来到公海分赃,一致同意如下分赃策略:
首先,P 个海盗通过抽签决定 1 - P 的序号。然后由第 1 号海盗提出一个分配方案(方案应给出每个海盗分得的具体数量),如果能够得到包括 1 号在内的绝对多数(即大于半数)同意,则按照该分配方案执行,否则 1 号将被投入大海喂鲨鱼;而后依次类似地由第 2 号、第 3 号等等海盗提出方案,直到能够获得绝对多数同意的方案出现为止,或者只剩下最后一位海盗,其独占所有钻石。请编写一个程序,给出第 1 号海盗的钻石分配方案中自己分得的钻石数量。
附带的三个假定:
- “聪明”与“贪婪”假定:每个海盗总能够以本人利益最大化作为行为准则;
- “人性化”假定:在能够取得尽量多钻石的情况下,海盗不会故意致同伙于死地;
- “无偏见”假定:海盗之间没有个人恩怨,分给其他海盗钻石的次序以小序号优先为原则。
输入格式:
输入在一行中给出 2 个正整数 D 和 P(3≤P≤D≤100)。
输出格式:
输出第 1 号海盗的钻石分配方案中自己分得的钻石数量。
输入样例:
10 7
输出样例:
6
这个题很有意思,之前这类题我也在博弈论的书上看到过,第一次写关于这个问题的算法,也是很新奇。
如果写在纸上,就不难发现他们的规律 让我们来写一下
(1)两个人
1 海盗无论自己得到多少,2肯定不同意,因为没有超过半数,所以只有 1 把所有的财产给 2 ,才能活命。
所以分配的结果为 : 0,D
(2)三个人
1 为了拉选票,肯定要笼络那些没有金币的人,那么金额为0就是首选的笼络人才,而上面我们能看到 此刻的 2 金额为 0,其次打击财产最多的人(因为你无论给他多少(自身盈利的情况下)他都不会满足,所以不用考虑他的分配),所以 3 金额变成 0
所以分配的结果为 :D-1,1,0
(3)四个人
同样适用(2)的理论 那么此刻的 2 金额一定为 0 ,最后的人即 4 为拉拢对象,但是这样还不会超过半数,那么 3 就会比上次的多分配一枚金币
所以分配的结果为 :D-3,0,2,1
(4)五个人 (超过一大半也就是有 3个人支持)
同上面的理论,拉选票就从金额最小的人(0个金币)开始,如果不够,则考虑1个金币的人,如果人数够了,那么剩余人将分不到金币(自身利益最大化)
所以分配的结果为 :D-3,0,1,0,2
慢慢慢慢大家就会发现 海盗的人数超过三个人的时候就会出现规律
(5)六个人 分配的结果:D-4,0,1,2,1,0
(6)七个人 分配的结果:D-4,0,1,2,0,0,1
(7)八个人 分配的结果:D-5,0,1,2,0,1,1,0
(8)九个人 分配的结果:D-5,0,1,2,0,1,0,0,1
(9)十个人 分配的结果:D-6,0,1,2,0,1,0,1,1,0
发现规律了吗?
没错每次只需要给上一次金币数为0的家伙一枚金币,再给其中一个上一次得到一枚金币的家伙两枚金币,第一个海盗选票就超过一大半了!
那么转化为数学规律 当人数超过三个人的时候 第一个海盗得到的金币为: D - (P / 2 + 1)
代码如下:
#include<iostream>
using namespace std;
int main(void){
int D,P;
cin>>D>>P;
if(P==3) cout<<D-1<<endl;
else cout<<D-(P/2+1)<<endl;
return 0;
}
原创链接,感谢老哥:https://blog.csdn.net/TOBEALISTENNER/article/details/79896856