zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    微信小程序之自定义toast弹窗
    NPOI 设置导出的excel内容样式
    NPOI excel导出快速构建
    GridView 基本使用
    jqgrid 各种方法参数的使用
    经典SQL语句大全
    jqgrid 加载时第一页面只显示多少条数据
    sqlserver2008 调试存储过程
    jqgrid 上移下移单元格
    jgrid 选择器 C#控件
  • 原文地址:https://www.cnblogs.com/hxer/p/5661322.html
Copyright © 2011-2022 走看看