hdu-1538 A Puzzle for Pirates

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1538

题目类型:

模拟

题意概括:

有1~n,n个海盗,m块金子,第n个海盗要提出一个分金方案,如果有一半以上的人同意,就立刻分金,反之就将这个人扔下水里,问所有情况都是最优解的情况下,要给第p个海盗分多少金?

解题思路:

如果只有一个人,所以肯定是给自己。

如果有两个人,那么自己将所有的钱都给自己,那么自己也同意分配,就可以得到一半以上的人的同意。

如果有三个人,第一个人知道如果不同意三号,那么自己绝对分不到钱,所以三号给多少,一号都会同意,有比没有强嘛,所以,三号只需要给一号一枚金币,剩下的全都收到囊中即可。

如果有四个人,如果第四个人死了,就像上种情况一样,所以只需要给二号一枚金币,就可以获得一半的支持。

........

以此类推,只要第n个海盗给自己编号奇偶性相同的海盗各一枚金币,即可。那么问题就来了...

如果得到的金子不够贿赂怎么办,也就是m*2<n的情况下,那就不是钱不钱的问题了,那就是小命要紧了,具体分析一下:

假如有500个海盗,但是只有100枚金币,怎么办?

对于201号来说,自己不能拿金币,并且把金币给除自己之外的其他奇数号海贼就能存活

对于202号来说,自己同样不能拿金币,并且吧金币给除了自己之外的其他偶数号海贼就能存活

对于203来说,至少需要102个人的支持,但是自己贿赂的拿金子获得的海盗加上自己,只能拿到101票,所以203必死,

对于204,如果自己死了,203必死,所以203一定会支持自己,所以自己吧金币分给之前的前200号偶数,一共可以得到100+1(203)+1(204),自己可以保证不死。

对于205号,204,203已经有了保全之策,所以他们是不会支持205的,所以205必死。

对于206呢,虽然205必死,会支持他,但是还是缺一票,所以必死。

对于207呢,205和206之前是必死,会支持他,但是加上自己以及100个保命名额,还是必死

对于208号,205,206.,207因为后面是必死的,肯定会支持208成功,那么208刚好能凑齐104票,得以保命。

所以,由此得到结论:n=2*m+2^k的情况下,是可以保命的状态,反之则为危险状态原因如下:

首先对于n来说,有m票贿赂,但是对于2*m+2^(k-1)以前必死的死,他们会支持2*m+2^(k-1),因为他们肯定拿不到钱,而且支持2*m+2^(k-1),另外根据杀人原则,希望之后的人都死,轮到2*m+2^(k-1)决策的时候保命就行了。

同理2*m+2^(k-1)到2*m+2^k之间的2^(k-1)-1个人来说,他们必死,所以必定支持2*m+2^k,加上m个金币贿赂的,加上他自己,刚好有m+2^(k-1)。这样刚好凑齐一半,可以不死。

所以:2*m+2^k的人可以保命,否则必死。

我们考虑一下分金币情况:

对于第2*m+2^k个人来说,他可以保命,肯定分不到金子,而他手上的m个金子,可以贿赂m个人,但是具体是哪些人是不定的。则不管是不能分到金子,还是可能分不到金子的人来说,结果都为0。

对于2*m+2^(k-1)到2*m+2^k之间的来说,他们的决策是必死,而在他们决策的时候,其它人分得金币情况也为0。

我们来解释一下金币的不确定性:

金币数量的不确定性:由上面的推理可知, 当n=2m+2时, 上一轮推理没有分到金币的人的金币数量首次具有不确定性, 并且在n>2m+2时, 这种不确定性一定会延续下去, 轮到因为n号决策者之前的一个人决策时, 那个人肯定分不到金币了, 所以在上一轮推理中没有分到金币的人的个数一定大于m。

综上所述就是该题的解题思路,非常感谢大神的解题思路,给我带来了太多的灵感,参考链接:

http://blog.csdn.net/acm_cxlove/article/details/7853916#comments

题目:

A Puzzle for Pirates

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

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.

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define C    240
#define TIME 10
#define inf 1<<25
#define LL long long
using namespace std;
//保存2的幂
int fac[15]={2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
void slove(int n,int m,int p){
    //金币够贿赂的情况
    if(n<=2*m){
        //不是决策者,而且奇偶性相同,都能被贿赂
        if(n!=p&&(n%2==p%2))
            printf("1\n");
        //剩下的都是决策者拥有
        else if(n==p)
            printf("%d\n",m-(n-1)/2);
        else
        //其余人分不到金币,他们的决策不影响全局
            printf("0\n");
        return ;
    }
    //这时候的不同在于决策者不能拿金币
    else if(n==2*m+1){
        if(p<2*m&&p&1)
            printf("1\n");
        else
            printf("0\n");
        return ;
    }
    int t=n-2*m,i;
    //这是刚好保命的情况,对于决策者来说,肯定没有金币
    //对于其它人来说,要么肯定没有金币,要么可能没有金币,不确定性
    for( i=0;i<14;i++){
        if(t==fac[i]){
            printf("0\n");
            return;
        }
    }
    for( i=1;i<14;i++)
        if(t<fac[i]){
            //决策者必死
            if(p>2*m+fac[i-1]&&p<2*m+fac[i])
                 printf("Thrown\n");
            else
                 printf("0\n");
            return ;
        }
}
int main(){
    int t,n,m,p;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&n,&m,&p);
        slove(n,m,p);
    }
    return 0;
}  
时间: 2024-10-11 01:47:26

hdu-1538 A Puzzle for Pirates的相关文章

HDU 1538 A Puzzle for Pirates (海盗分金问题)

A Puzzle for Pirates Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 508    Accepted Submission(s): 167 Problem Description A bunch of pirates have gotten their hands on a hoard of gold pieces a

HDU 1538 A Puzzle for Pirates 经典海盗分金币

题目:这是一个经典问题,有n个海盗,分m块金子,其中他们会按一定的顺序提出自己的分配方案,如果50%以上的人赞成,则方案通过,开始分金子,如果不通过,则把提出方案的扔到海里,下一个人继续. 首先我们讲一下海盗分金决策的三个标准:保命,拿更多的金子,杀人,优先级是递减的. 同时分为两个状态稳定状态和不稳定状态:如果当n和m的组合使得最先决策的人(编号为n)不会被丢下海, 即游戏会立即结束, 就称这个状态时"稳定的". 反之, 问题会退化为n-1和m的组合, 直到达到一个稳定状态, 所以乘

hdu 4662 MU Puzzle

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4662 MU PuzzleTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1296    Accepted Submission(s): 539 Problem Description Suppose there are the symbols

HDU 4021 24 Puzzle (拼图)

24 Puzzle Problem Description Daniel likes to play a special board game, called 24 puzzle. 24 puzzle is such a game that there are tiles with the number 1 to 23 in a play board like the follow picture: The '#' denotes the positions that the tiles may

HDU 1538

http://acm.hdu.edu.cn/showproblem.php?pid=1538 经典经济学问题,海盗分金 分析http://www.guokr.com/article/41423/ #include <iostream> #include <cstdio> using namespace std; int a[15]; int main() { a[0] = 2; for(int i = 1; ; i++) { a[i] = a[i-1] * 2; if(a[i] *

HDU 4662 MU Puzzle:找规律

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4662 题意: 初始字符串为"MI". 有三个操作: (1)将'M'之后的所有字符翻倍.For example: MIU to MIUIU. (2)将'III'变为一个'U'.For example: MUIIIU to MUUU. (3)删除'UU'.For example: MUUU to MU 给你一个字符串s,问你是否能将初始字符串"MI"通过一系列操作变为s.

【HDU1538】A Puzzle for Pirates(经典的海盗问题)

[题目] 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 pirat

人生第一个快速幂的题(HDU - 1097--A hard puzzle )

题意: 最简单的快速幂.给你两个数n和m,求n^m的最后一位: 解题思路: 额,快速幂就很简单了,这里只要最后一位可以一对每次运算都%10: 代码: #include<cstdio> #include<cstring> #include<algorithm> #include <iostream> using namespace std; #define N 100000 long long n,m; long long pow_(long long n,l

HDU 2931 Digit Puzzle 搜索 DFS

#include<cstdio> #include<cstring> int num[3],tot,n,f; char s[3][100],ans[3][100]; int check() { char str[100]; int a=0,b=0,c; for(int i=0;i<num[0];i++) a=a*10+s[0][i]-'0'; for(int i=0;i<num[1];i++) b=b*10+s[1][i]-'0'; c=a*b; for(int i=n