HDU1538——A Puzzle for Pirates(博弈论,海盗分金问题)

本文详细解析了经典的海盗分金问题,介绍了海盗们如何通过民主投票的方式决定黄金的分配,并确保自身利益最大化的同时避免被抛入海中。文章还提供了一个示例性的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A Puzzle for Pirates

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 911    Accepted Submission(s): 351


Problem Description
A bunch of pirates have gotten their hands on a hoard of gold pieces and wish to divide the loot. They are democratic pirates in their own way, and it is their custom to make such divisions in the following manner: The fiercest pirate makes a proposal about the division, and everybody votes on it, including the proposer. If 50 percent or more are in favor, the proposal passes and is implemented forthwith. Otherwise the proposer is thrown overboard, and the procedure is repeated with the next fiercest pirate. 
All the pirates enjoy throwing one of their fellows overboard, but if given a choice they prefer cold, hard cash, the more the better. They dislike being thrown overboard themselves. All pirates are rational and know that the other pirates are also rational. Moreover, no two pirates are equally fierce, so there is a precise pecking order — and it is known to them all. The gold pieces are indivisible, and arrangements to share pieces are not permitted, because no pirate trusts his fellows to stick to such an arrangement. It's every man for himself. Another thing about pirates is that they are realistic. They believe 'a bird in the hand is worth two in the bush' which means they prefer something that is certain than take a risk to get more, where they might lose everything. 

For convenience, number the pirates in order of meekness, so that the least fierce is number 1, the next least fierce number 2 and so on. The fiercest pirate thus gets the biggest number, and proposals proceed in the order from the biggest to the least. 

The secret to analyzing all such games of strategy is to work backward from the end. The place to start is the point at which the game gets down to just two pirates, P1 and P2. Then add in pirate P3, P4, ... , one by one. The illustration shows the results when 3, 4 or 5 pirates try to divide 100 pieces of gold. 



Your task is to predict how many gold pieces a given pirate will get.
 

Input
The input consists of a line specifying the number of testcases, followed by one line per case with 3 integer numbers n, m, p. n (1 ≤ n ≤ 10^4) is the number of pirates. m (1 ≤ m ≤ 10^7) is the number of gold pieces. p (1 ≤ p ≤ n) indicates a pirate where p = n indicates the fiercest one. 
 

Output
The output for each case consists of a single integer which is the minimal number of gold pieces pirate p can get. For example, if pirate p can get 0 or 1 gold pieces, output '0'. If pirate p will be thrown overboard, output 'Thrown'. 
 

Sample Input
  
3 3 100 2 4 100 2 5 100 5
 

Sample Output
  
0 1 98
Hint
Hint
The situation gets complicated when a few gold pieces were divided among many pirates.
 

Author
Otter
 

Source



经典的海盗分金问题。

有n个海盗瓜分数量为m的金币,每个海盗轮流提出一个瓜分方案,然后进行投票,如果有半数以上的海盗支持,则进行分配,否则,提出方案的海盗将会被扔进海里,由下一个海盗提供新的方案。

对于每一个海盗,肯定是想要,先保命,然后拿尽可能多的金币。


具体的分析可以看这篇博客,我就不再重复一遍了。http://blog.youkuaiyun.com/acm_cxlove/article/details/7853916


#include <cstdio>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,p;
        scanf("%d%d%d",&n,&m,&p);
        int res=-1;
        if(n<=2*m+1){
            if(p==n){
                res=m-(n-1)/2;
            }
            else if((p%2)==(n%2)){
                res=1;
            }
            else{
                res=0;
            }
        }
        else{
            int ok=0;
            int temp;
            for(int i=20;i>=1;i--){
                if(n==2*m+(1<<i)){
                    ok=1;
                    res=0;
                    break;
                }
                else if(n>(2*m+(1<<i))&&n<(2*m+(1<<(i+1)))){
                    temp=2*m+(1<<i);
                    break;
                }
            }
            if(ok==0){
                if(p>temp){
                    res=-1;
                }
                else{
                    res=0;
                }
            }
        }
        if(res==-1){
            puts("Thrown");
        }
        else{
            printf("%d\n",res);
        }
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值