海盗分赃

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

逆向思考,每个海盗只需争取幸存者中超过半数的票。以20个宝石,5个海盗为例。

假如只剩4号5号两个海盗,提方案的4号海盗只能提出给自己0个钻石,否则肯定被5号海盗拒绝,即方案为4、5号:0,20。

则剩下3个海盗的时候,提方案的3号海盗只需给4号海盗1个钻石就能争取到他的一票,即方案为3、4、5号:19,1,0。

同理根据上一步,剩下4个海盗的时候,提方案的2号海盗只需争取到上一步最惨的4号5号的票就能过半,即方案为2、3、4、5号:17,0,2,1。

于是5个海盗都在的时候,提方案的1号海盗只需提出17,0,1,0,2,争取到上一步最惨的3号和5号两个海盗的票即可。


由于最终只需输出1号给自己分的钻石数,我们可以对上一轮的人按钻石数从小到大进行排序,给最惨的一半人加1个钻石。

而如果要求输出从1号提出的具体方案。则需要用结构体(包含海盗编号和钻石数两个变量)。在最后按海盗编号进行排序,输出钻石即可。

/*2015.8.5cyq*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
	int D,P;
	cin>>D>>P;
	vector<int> a(P+1);//a[i]倒数第i个海盗,a[P]为最先提方案的1号海盗
	//若只剩3个人,提方案的海盗只需分给倒数第二个海盗1个钻石就能争取到票 
	a[1]=0;
	a[2]=1;
	a[3]=D-1;

	for(int i=4;i<=P;i++){
		sort(a.begin()+1,a.begin()+i);
		int used=0;
		int j;
		for(j=1;j<=i/2;j++){//给半数钻石最少的海盗多分1个
			++a[j];
			used+=a[j];
		}
		for(  ;j<i;j++)//剩下的海盗都给0个钻石
			a[j]=0;

		a[i]=D-used;
	}
	cout<<a[P]<<endl;
	return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值