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\n");
52         else printf("Bob will win\n");
53     }
54     return 0;
55 }

 

 
 
posted @ 2018-10-04 16:08  YuWenjue  阅读(322)  评论(0编辑  收藏  举报