hdu-1538 A Puzzle for Pirates

2024-03-10 21:50
文章标签 hdu 1538 puzzle pirates

本文主要是介绍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;  
}  

 

转载于:https://www.cnblogs.com/love-sherry/p/6964878.html

这篇关于hdu-1538 A Puzzle for Pirates的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/795633

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时