• 海盗分金--大于半数才成立


    B  海盗分金币啦

    Time Limit:1000MS  Memory Limit:65535K

    题型: 编程题   语言: 无限制

    描述

    现在有n个海盗,他们抢到了m个金币,现在他们准备分钱,但是由于他们聪明绝顶,

    又不想直接平均分配,都想分到更多的钱,于是他们就想出了一种方法,就是让他们

    按顺序排成一排,编号为1~n,现在由第一个人开始,每个人提出一种方案,如果这个

    方案有除分钱的人以外一半或者一半以上的人同意,那么他们就按照这个方案分钱,否

    则的话,分钱的人就要被拖去喂鲨鱼,继续由下一个人分钱,直到有人提出一个满意的方案。

     

    现在你是第一个分钱的人,你需要保证自己存活的情况下令自己获得的钱数尽可能的多。

    PS

    1.生命>金钱

    2.当其他海盗能获得的金钱比分钱的海盗分给他的金钱多或者一样时,他会反对你分配的方案。



    输入格式

    第一行输入一个T(1<=T<=10000)

    接下来T行输入n和m(1<=n<=1000,1<=m<=10000)

    输出格式

    输出你能得到的金钱数,当你死亡时,输出-1,每个case一行。

    输入样例

    2

    5 100

    2 100

    输出样例

    97

    -1

    Hint

    当5个人分100个金币的时候

    假定五个人按照分钱顺序写为1~5号

    从后向前推,如果1至3号强盗都喂了鲨鱼,只剩4号和5号的话,5号一定投反对票让4号喂鲨鱼,以独

    吞全部金币,四号必死。所以,4号惟有支持3号才能保命。

    3号知道这一点,就会提出“100,0,0”的分配方案,对4号、5号一毛不拔而将全部金币归为已有,

    因为他知道4号即使一无所获,但为了生命着想还是会投赞成票,他的方案即可通过。

    不过,2号推知3号的方案,就会提出“98,0,1,1”的方案,即放弃3号,而给予4号和5号各一枚金

    币。由于该方案对于4号和5号来说比在3号分配时更为有利,他们将支持他而不希望他出局而由3号来

    分配。这样,2号将拿走98枚金币。

    同样,2号的方案也会被1号所洞悉,1号并将提出(97,0,1,2,0)或(97,0,1,0,2)的方案,

    即放弃2号,而给3号一枚金币,同时给4号(或5号)2枚金币。由于1号的这一方案对于3号和4号(或5号)

    来说,相比2号分配时更优,他们将投1号的赞成票,1号的方案可获通过,97枚金币可轻松落入囊中。这

    无疑是1号能够获取最大收益的方案了!

    答案是:1号强盗分给3号1枚金币,分给4号或5号强盗2枚,自己独得97枚。分配方案可写成

    (97,0,1,2,0)或(97,0,1,0,2)。

     

    当只有2个人分100金币时:

    推理同上:你不可能存在令最后一人满意的方案

     

    一道模拟题,wa了我很多次,原因是因为我没想到如果某个海盗一定死了时,它会成为上一个海盗的“死党”,所以上一个海盗可以省一个金币,甚至有可能活过来。开始的时候我但但是模拟了题目的数据,一直写到13 100,果然太天真,100个金币你分很多个都分不完了,所以我就开始用金币为5来模拟,就发现了13 5 是0,14 5 是-1但是17 5是0,又奇迹地复活了,因为它有三个连续的死党了。

      所以,分析完后,根据DP的思路,从后开始计数。一路向上推,打个表(不然超时),用个数组

    a[i][j],表示,有i个海盗,j个金币的时候最多能拿多少钱。从而判断a[i-1][j];他的上一个能拿多少钱?如果它死了,就要找出有多少个连续的死党,我就不需要用钱贿赂它了,如果他是0,也好办,贿赂它只需要用money=need*1;其中need=i/2;就是当前人数的一半,这样能确保他>50%的,模拟下吧。如果他>0,那么,就有一个海盗要用2个金币来贿赂啦,所以money=need+1;

    打个表,以后查询o(1)..233ms过了。。说多都是泪啊。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int a[1002][10002];
    int find (int pos,int money)//找到有多少个连续的”死党“
    {
        int i;
        int i_count=0;
        for (i=pos;i>=1;i--)
        {
            if (a[i][money]!=-1)
            {
                return i_count;
            }
            i_count++;
        }
        return i_count;
    }
    void init ()
    {
        int i,j;
        int t;
        for (j=1;j<=10000;j++)
        {
            a[1][j]=j;//拿到
            a[3][j]=j;//get
        }
        for (j=1;j<=10000;j++)
        {
            a[2][j]=-1;//死忙
        }
        for (j=1;j<=10000;j++)
        {
            a[4][j]=j-2;//1---4要特殊处理,,自己看看"规律"吧
        }
        int need;
        int money;
        for (i=5;i<=1000;i++)
        {
            for (j=1;j<=10000;j++)
            {
                 need=i/2;//需要贿赂的人数
                 if (a[i-1][j]==0)
                 {
                     money=need;//就需要这么多个1
                 }
                 else if (a[i-1][j]==-1)//他会死的话..可以小很多个
                 {
                     t=find(i-1,j);
                     money=need-t;//还可以少t个
                 }
                 else
                 {
                     money=need+1;//4个海盗时是不符合这个规矩的
                 }
                 
                 if (j<money)//不够钱..死了
                 {
                     a[i][j]=-1;
                 }
                 else 
                 {
                     a[i][j]=j-money;
                 }
            }
        }
        return ;
    }
    void work ()
    {
        int n,m;
        scanf ("%d%d",&n,&m);
        printf ("%d
    ",a[n][m]);
        return ;
    }
    int main ()
    {
        init ();
        int t;
        scanf ("%d",&t);
        while (t--)
        {
            work ();
        }
        return 0;
    }
  • 相关阅读:
    Android--多线程之Handler
    Android--Service之基础
    Android--UI之Fragment
    Android--多线程之图文混排
    python常用模块
    python应用之socket编程
    网络编程socket理论一
    pycharm Launching unittests with arguments
    python字符串格式化
    python数据类型之三
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5137999.html
Copyright © 2020-2023  润新知