NYOJ 994 海盗分金 逆向递推

链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=994

题意:

有n个海盗劫得了窖藏的m块金子,并准备瓜分这些战利品。按照古老流传下来的分金法则,由最厉害的一名海盗提出一个分金方案,假如有不小于一半的海盗(包括自己)支持这个方案,则按这个方案分,否则把这个海盗扔进海里,重复由下一个厉害的海盗提出方案。

大家都知道,所有海盗都是贪婪的,虽然他们都乐于看到自己的同伴被扔进海里,但是他们还是希望在保命的前提下分的最多的金子,现在已经按海盗的厉害程度进 行了编号,最厉害的海盗为最大号,依次到小,那么第 k 号海盗能分的多少金。(如果他的得金数不能确定,输出0)

输入:(1 ≤ n ≤ 10^4) (1 ≤ m ≤ 10^7)(1 ≤ k ≤ n)

输出:第k个海盗能获得的金币数

参考博文:http://blog.csdn.net/y990041769/article/details/22858781

思路:如果从上往下分析,将会受到小号策略的影响,不妨逆向从小号(只剩1和2)开始往大递推出关联,关联详见博文;

此题的关键必须深刻理解海盗之间的规则:

1.即使没有金币,也必须要保住性命;

如在n > 2*m部分,第一个稳定状态(n-2*m为2^k,同时也是确定分配方案的海盗的id)就是通过给1~2m海盗分配每人分配1个金币收买,剩下的支持票属于就是来自于n-2^(k-1)~n怕死而支持的海盗;

2.在保命的前提下,能获得金币最好;

在n = 2*m+1时,为了保命只能将m个金币全部给奇数好的海盗,但是在n = 2m+2时,就可以利用2m+1这一点,可选的海盗数就为101个,这里就产生了不确定性;

即当第一个稳定状态n >= 2m+2时,任意小于等于n的海盗要不就是>2m原本就不能获得,只是存活下来,结果为0。要不就是因为上一个状态的不确定性,导致不能确定是否会获得金币,结果也是0;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string.h>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<cmath>
 8 #include<stdlib.h>
 9 #include<time.h>
10 #include<stack>
11 #include<set>
12 #include<map>
13 #include<queue>
14 using namespace std;
15 #define rep0(i,l,r) for(int i = (l);i < (r);i++)
16 #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
17 #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
18 #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
19 #define MS0(a) memset(a,0,sizeof(a))
20 #define MS1(a) memset(a,-1,sizeof(a))
21 #define MSi(a) memset(a,0x3f,sizeof(a))
22 #define inf 0x3f3f3f3f
23 typedef long long ll;
24 #define A first
25 #define B second
26 #define MK make_pair
27 template<typename T>
28 void read1(T &m)
29 {
30     T x=0,f=1;char ch=getchar();
31     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
32     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
33     m = x*f;
34 }
35 template<typename T>
36 void read2(T &a,T &b){read1(a);read1(b);}
37 template<typename T>
38 void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
39 template<typename T>
40 void out(T a)
41 {
42     if(a>9) out(a/10);
43     putchar(a%10+‘0‘);
44 }
45 int T,kase = 1,i,j,k,n,m,c;
46
47 int main()
48 {
49     read1(T);
50     while(T--){
51         read3(n,m,c);
52         int ans = -1;
53         if(n <= 2*m+1){
54             if(c == n) ans = m-(n-1)/2;
55             else if((c&1) == (1&n)) ans = 1;
56             else ans = 0;
57         }else{
58             n -= 2*m;   //找到第一个稳定状态
59             while(__builtin_popcount(n) != 1)  //是否为2的幂次方
60                 n &= (n-1);
61             if(n+2*m >= c) ans = 0;
62         }
63         if(ans == -1) puts("Thrown");
64         else printf("%d\n",ans);
65     }
66     return 0;
67 }
时间: 2024-09-30 19:35:50

NYOJ 994 海盗分金 逆向递推的相关文章

海盗分金问题(博弈)

NBUOJ 2680:海盗分金 题意: 有N个海盗要分M金币,将N个海盗从1-N编号,由第一个人提出分配方案,一人一票(分配者也拥有一票),超过半数同意方案才被通过,否则他将被扔入大海喂鲨鱼,接下来由下一人分配,以此类推. 分析:从3个人的状态往后推,每次处理出当前分配方案下的被分到0,1 金币的海盗数量,当前被分到0,下次并然分到1,当前分到1的判断是否需要分配2才能满足通过条件,最后输出分配剩余的金币数即可. 代码: 1 #include "cstdio" 2 #include &

算法浅谈——递归算法与海盗分金问题

本文始发于个人公众号:TechFlow 最近看到一道很有意思的问题,分享给大家. 还是老规矩,在我们聊算法问题之前,先来看一个故事. 传说中,有5个海盗组成了一支无敌的海盗舰队,他们在最后一次的寻宝当中找寻到了100枚价值连城的金币.于是,很自然的,这群海盗面临分赃的问题.为了防止海盗内讧,残忍的海盗们制定了一个奇怪的规则: 他们决定按照功劳大小对五个人进行编号,由编号小的海盗先提出分配方案.如果方案能够得到大多数人的同意,那么就按照他提出的方案进行分配.如果不能通过,说明他已经失去了威望,海盗

海盗分金的故事

两周时间,身体疲惫的要死. 近来,每晚一梦的习惯又开始了. 昨晚,睡了好久,做了很诡异的梦,把自己纠缠到醒之后,好想拿起手机问问是不是很多人都在看世界杯. 朦胧中细想,这还用问么?楼上还有声音,估计正在等待看巴西和德国大战. ---------------------------------分割线---------------------------------------- 海盗分金,是一个经济学问题.整个故事喜感到爆,原理是用最小代价获取最大利益.但,前提是每个人都必须是智商高到爆. 假如任

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

海盗分金的问题

海盗分金好像是个博弈论的老问题了. 本科的时候听GXL谈到过问题本身,没有去解.昨天,LX问到我这个问题.思考了一下解法,不知道对不对,写在这里. 流行的问题是这样: 五个海盗抢到了100枚金币,他们决定这么分: 1.抽签决定自己的号码 :5  4  3  2  1: 2.首先,由5号提出分配方案,然后5人共同进行表决,如果有半数或半数以上人同意时,就按照他的提案进行分配,否则5号将被扔入大海喂鲨鱼: 3.在5号死后,由4号提出分配方案,然后4人进行表决,如果有半数或半数以上人同意时,就按照他的

海盗分金问题SQL求解(贪心算法)

问题 经济学上有个"海盗分金"模型:是说5个海盗抢得100枚金币,他们按抽签的顺序依次提方案:首先由1号提出分配方案,然后5人表决,超过半数同意方案才被通过,否则他将被扔入大海喂鲨鱼,依此类推,假设海盗是足够聪明的先利己再伤人,最后方案是怎样的? 网上百度来的的代码 with a as (select 101 - rownum n from dual connect by rownum <102), max_one as (select max(n) max1 from a),

poj 2096 Collecting Bugs 【概率DP】【逆向递推求期望】

Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 3523   Accepted: 1740 Case Time Limit: 2000MS   Special Judge Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material s

海盗分金

/* 5个海盗抢到了100颗宝石,每一颗都一样的大小和价值. 他们决定这么分: 1.抽签决定自己的号码(1,2,3,4,5) 2.首先,由1号提出分配方案,然后大家5人进行表决,当且仅当半数和超过半数的人同意时,按照他的提案进行分配,否则将被扔入大海喂鲨鱼. 3.如果1号死后,再由2号提出分配方案,然后大家4人进行表决,当且仅当半数和超过半数的人同意时,按照他的提案进行分配,否则将被扔入大海喂鲨鱼. 4.以次类推...... 条件: 每个海盗都是很聪明的人,都能很理智的判断得失,从而做出选择.

好玩的智力小游戏(海盗分金)

 海盗的难题(Ian Stewart) 数学的逻辑有时会导致看来十分怪异的结论. 一般的规则是.假设逻辑 推理没有漏洞. 那么结论就必然站得住脚,即使它与你的直觉矛盾. 1998 年9月,加利福尼亚州帕洛阿 尔托的Stephen M. Omohundro寄给我一道难题, 它恰好就属于这一类.这难题已经流传 了至少十年,可是Omohundro对它作 了修改,使它的逻辑问题变得分外复杂了. 先来看看此难题原先的形状. 10名海盗抢得了窖藏的100块金子,并打算 瓜分这些战利 品.这是一些讲民主的