zoukankan      html  css  js  c++  java
  • POJ1704

    emmmm于是我咕咕咕了图论相关总结和数论相关总结。

    现在暂时欠着吧....NOIP前一定补上,不会咕不会咕

    于是先来水一道博弈,然而我看完题解才会.....

    POJ1704

    格鲁吉亚和鲍勃决定玩自己发明的游戏。他们在纸上绘制一排网格,将网格从左到右依次为1,2,3,......,并将N个西洋棋棋子放在不同的网格上,如下图所示: 
    格鲁吉亚和鲍勃依次移动西洋棋棋子。每次玩家选择一个棋子,并将其移动到左边而不越过任何其他西洋棋棋子或横跨左边缘。玩家可以自由选择棋子移动的步数,其中约束棋子必须至少移动一步,一个网格最多可以包含一个棋子。无法移动的玩家输掉游戏。 
    基于女士优先的原则,格鲁吉亚总是首发。假设格鲁吉亚和鲍勃都在比赛中尽了最大努力,也就是说,如果他们中的一个知道赢得比赛的方式,他或她将能够执行。 
    鉴于n个西洋棋棋子的初始位置,你能预测谁将最终赢得比赛吗? 

    输入

    输入的第一行包含单个整数T(1 <= T <= 20),即测试用例的数量。然后是T案例。每个测试用例包含两行。第一行由一个整数N(1 <= N <= 1000)组成,表示西洋棋棋子的数量。第二行包含N个不同的整数P1,P2 ... Pn(1 <= Pi <= 10000),它们是n个西洋棋棋子的初始位置。

    输出

    对于每个测试案例,如果格鲁吉亚将赢得比赛,打印一行“Georgia will win”; 如果鲍勃将赢得比赛,“Bob will win” 否则'Not sure'。
     

    先将棋子按照位置升序排序,从后往前将他们两两绑定,显然若是偶数个棋子,最后刚好绑定结束,但若是奇数个,最后就会多出来一枚棋子
    这枚多出来的棋子显然只可能是左边的第一颗棋子,那么我们将这颗棋子和左边缘绑定起来
    从左到右观察
    我们可以发现,对于第一堆,显然有意义的只有堆之间两枚被绑定的棋子的距离,同样我们能发现,第一枚棋子无论向左移动多少个位置
    显然第二枚棋子总能移动相同的格子。也就是说,一对棋子与另一对棋子之间有多少个空位置堆结果是没有影响的,那么我们就只需要考虑同一对棋子之间的距离
    我们把每一对棋子之间的空位视作一堆石子,在对手移动每对石子靠右的那一颗时,移动几位就相当于取几个石子,各堆的石子取尽,相当于不能再取石子

    但是显然存在一些情况,因为题目规则并没有限制,所以如果我将每一对的棋子的左端棋子移动,就会导致堆中石子数增加
    然而显然的是,若对手这么做要破坏棋局,我们可以将当前堆的右端棋子移动相同的步数,使堆中的棋子恢复到原来的数量,这样棋局就变的相当于没有改变
    所以这种状况我们可以直接无视。
    这样我们就转化成了简单的NIM问题

     

    于是我们能够发现,根本不存在Not sure。因为NIM博弈,不存在平局!

     1 #include<iostream>
     2 #include<iomanip>
     3 #include<cstdio>
     4 #include<ctime>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<algorithm>
     8 #include<cstdlib>
     9 #include<stack>
    10 #include<queue>
    11 #include<map>
    12 #include<vector>
    13 using namespace std;
    14 const int maxn = 2100;
    15 int T;
    16 int n, p[maxn];
    17 int shiki[maxn], top = 0;
    18 
    19 inline int read() {
    20     int x = 0, y = 1;
    21     char ch = getchar();
    22     while(!isdigit(ch)) {
    23         if(ch == '-') y = -1;
    24         ch = getchar();
    25     }
    26     while(isdigit(ch)) {
    27         x = (x << 1) + (x << 3) + ch - '0';
    28         ch = getchar();
    29     }
    30     return x * y;
    31 }
    32 
    33 int main() {
    34     T = read();
    35     while(T--) {
    36         memset(p, 0, sizeof(p));
    37         memset(shiki, 0, sizeof(shiki));
    38         n = read(); top = 0;
    39         for(int i = 1; i <= n; ++i) p[i] = read();
    40         sort(p + 1, p + n + 1);
    41         for(int i = n; i >= 1; i -= 2) {
    42             if(i == 1) {
    43                 shiki[++top] = p[i] - 1;
    44                 break;
    45             }
    46             shiki[++top] = p[i] - p[i - 1] - 1;
    47         } 
    48         int ans = 0;
    49         for(int i = 1; i <= top; ++i) 
    50             ans ^= shiki[i];
    51         if(ans) printf("Georgia will win
    ");
    52         else printf("Bob will win
    ");
    53     }
    54     return 0;
    55 }
     
     
  • 相关阅读:
    mysql中InnoDB存储引擎的行锁和表锁
    阿里云出海 埃森哲护航
    阿里云出海 埃森哲护航
    阿里云出海 埃森哲护航
    阿里云出海 埃森哲护航
    Python开发简单爬虫
    Python开发简单爬虫
    Python开发简单爬虫
    Python开发简单爬虫
    问大家一个问题,如何用1万元创业,每天利润达到500元?
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9742449.html
Copyright © 2011-2022 走看看