• 竞价2013编程之美初赛第一场第一题


    竞价

    题目如下:
    时间限制: 1000ms 内存限制: 256MB

    描述

    Alice和Bob都要向同一个商人购买钻石。商人手中有 N 颗钻石,他会将它们一颗颗地卖给他们,Alice和Bob通过竞价的方式来决定钻石的归属。具体的过程如下:商人首先指定其中一个人开始报价,之后两人轮流报价,要求是一定要比对方报的价格更高。任何时候,如果一个人不愿出价或者出不起价钱时,可以宣布弃权,则对手以最后一次报的价格将钻石买下。当然,如果两人都没钱,商人是不会卖钻石的。首次报价至少为 1,并且只能报整数的价钱。
    Alice和Bob特别爱攀比,因此他们都希望能比对方买到更多的钻石。Alice和Bob各自带了 CA 和 CB 的钱用于竞拍钻石。此外,Alice和商人有很不错的私人关系,因此商人总是会让Alice先报价。现在请问,在Alice和Bob都用最优策略的情况下,谁能买到更多钻石?假设双方都知道对方手中的现金数量,以及商人将要拍卖的钻石数量 N。

    输入

    输入文件包含多组测试数据。
    第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。
    每组数据为三个用空格隔开的整数 N,CA,CB,表示钻石的数量,以及双方带的现金数量。

    输出

    对于每组测试数据,输出一行"Case #X: Y",其中X表示测试数据编号,Y的取值为{-1, 0, 1},-1表示Alice买到的钻石会比Bob少,0表示两人能买到一样多,1表示Alice能买到更多钻石。所有数据按读入顺序从1开始编号。

    数据范围

    1 ≤ T ≤ 1000
    小数据:0 ≤ N ≤ 10; 0 < CA, CB ≤ 10
    大数据:0 ≤ N ≤ 105; 0 < CA, CB ≤ 106


    样例输入

    2

    4 3 5

    7 4 7

    样例输出
    Case #1: 0

    Case #2: 1

    这一题想了很久,思路基本都是对的,可惜最后还是放弃了没提交,现在看了别人的代码,理清了一下思路。n是宝石数目,a是Alice的钱币数目,b是bob的钱币数目。

    基本就是去找规律,每次要获取宝石,Alice和Bob都必须付出至少1个钱币的代价。获胜的条件是获取超过宝石数目n的一半的宝石(n/2 + 1),考虑到Alice在最小代价下能获取的宝石数目是a,那么Alice在此时最后到底能否获胜呢?这个取决于n的大小,于是可以根据n的大小分成以下三种情况来考虑:

    1.n > 2 * a;即n至少为2 * a + 1。自然会想到比较a和b的大小:

    当b > a时,即b至少为a + 1,此时Bob必然获胜,因为即便前面a个宝石全部让给Alice,Bob依然可以获取剩下的至少a+1个宝石;

    当b < a时,Alice必然获取,同上,因为即便前面b个宝石全部让给bob,Alice依然可以获取a个宝石,始终比bob的宝石多;

    当b = a时,两人买到的宝石一样多。

    2.n == 2 * a时,同上考虑:

    当b < a时,Alice获胜;

    当 b >= 2 * a + 2时,bob获胜,因为想要获胜就必须获取a + 1个宝石,因为Alice有a个宝石,Alice的最优策略是每次至少出1个钱币,所以bob每次必须用2个钱币才能获取一个宝石,所以即b至少为2*(a+1)时bob获胜;

    当b >= a && b < 2*a + 2时,两人最终获取的宝石一样多;

    3.当n < 2 * a时,此时情况最复杂,我当时就是被这里的细节给吓晕了,根据n的奇偶性分成两种情况:

    当n是奇数时,获胜需要的宝石数目是winner = n/2 + 1,因为a > n / 2,所以a的数目至少是等于winner,Alice的想要获胜(即拿到winner个宝石)的最优策略是每次用d = a / winner的钱币来获取一个宝石,bob必胜的情况是每次都付出比Alice的报价多1个(即d + 1个),所以bob至少需要(d + 1) * winner才能保证必胜,所以当b >= (d+1)*winner时,bob必胜;否则的话,Alice必胜。

    当n是偶数时,获胜的宝石数目winner2  = n / 2 + 1,平局(即两人拿到的宝石一样多)需要宝石数目是winner1 = n / 2,同样为了拿到winner2个宝石Alice每次付出d2  = a / winner2,为了拿到winner1个宝石Alice每次付出d1 = a / winner1,bob必胜的策略是每次付出(d1 + 1)拿到winner2个宝石,即当b >= (d1+1)*winner2时,bob必胜;Alice必胜的时候则是b< (d2 + 1) * winner1,即bob无法获得至少一半的宝石;当b>= (d2+1) * winner1 && b < (d1+1)*winner2时,两人获取的宝石一样多。

    问题分析清楚之后,代码就很好写了,而且小数据和大数据都可以顺利AC!

     1 #include<iostream>
     2 using namespace std;
     3 int main() {
     4     int T;
     5     cin >> T;
     6     int n, a, b;
     7     int k = 0;
     8     while(T--) {
     9         cin >> n;
    10         cin >> a;
    11         cin >> b;
    12         int result;
    13         cout << "Case #";
    14         cout << ++k;
    15         cout << ": ";
    16         if (n > 2 * a) {
    17             if (b > a)
    18                 result = -1;
    19             if (b == a)
    20                 result = 0;
    21             if (b < a)
    22                 result = 1;
    23             cout << result << endl;
    24             continue;
    25         }
    26         if (n == 2 * a) {
    27             if (b < a)
    28                 result = 1;
    29             if (b >= a && b <= 2 * a + 1) 
    30                 result = 0;
    31             if (b > 2 * a + 1)
    32                 result = -1;
    33             cout << result << endl;
    34             continue;
    35         }
    36         if (n < 2 * a) {
    37             if (n % 2 == 0) {
    38                 int temp1 = n / 2;
    39                 int temp2 = n / 2 + 1;
    40                 int d1 = a / temp1;
    41                 int d2 = a / temp2;
    42                 int smaller = (d2 + 1) * temp1;
    43                 int bigger = (d1 + 1) * temp2;
    44                 if (b < smaller)
    45                     result = 1;
    46                 if (b >= bigger)
    47                     result = -1;
    48                 if (b >= smaller && b <bigger)
    49                     result = 0;
    50             }
    51             else {
    52                 int temp = n / 2 + 1;
    53                 int d = a / temp;
    54                 int bigger = (d + 1) * temp;
    55                 if (b >= bigger)
    56                     result = -1;
    57                 else 
    58                     result = 1;
    59             }
    60             cout << result << endl;
    61         }
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    VC++对话框笔记
    STL中用erase()方法遍历删除元素
    VC++中不小心选错工程类型的解决办法
    directX中常用的数学计算
    VC++中string、char* 转换为LPCSTR
    判断空间上点是否在直线上
    vc6.0插件
    VC++常用定义(如SAFE_DELETE等)
    关于控件的AutoSize属性影响界面布局的问题解决
    C#判断日期是否正确(1900~今年,月份,天数)
  • 原文地址:https://www.cnblogs.com/chasuner/p/3019536.html
Copyright © 2020-2023  润新知