题目链接:
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; }