競價-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 }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM