http://poj.org/problem?id=1704
把数组倒置(17 14 12 9 7 6 5 1),将相邻棋子的间距视为一堆石子(2 1 2 0 0 3),那么题中所给操作即为把后一堆石子中的n个放到前一堆石子中,这样就转化为了阶梯博弈。用阶梯博弈的解法直接奇位异或就ok了。
在其他博客里还看到一种解法,从后向前两两分组,奇数个点则在最前加一个0结点。把两个结点间的间距看作一堆石子。
1. 若对手移动两个中的前一个,那么后一个一定可以移动同样多的位置
2. 若对手移动两个中的后一个,那么等同于从这堆石子中拿出n个
这不就是阶梯博弈么?对偶数堆的操作可以忽视,奇数堆异或即为解。干嘛说的好像很厉害的样子...
code:
#include<cstdio>
#include<cstdlib>
int data[1001] ;
int cmp(const void *a, const void *b){
return *(int *)a < *(int *)b ? -1 : 1 ;
}
int main(){
int t, n, i, j, sum ;
scanf("%d", &t) ;
while(t--){
sum = 0 ;
scanf("%d", &n) ;
data[0] = 0 ;
for(i=1; i<=n; i++)
scanf("%d", &data[i]) ;
qsort(data, n+1, sizeof(data[0]), cmp) ;
for(i=n; i>0; i-=2)
sum ^= (data[i] - data[i-1] - 1) ;
if(sum) printf("Georgia will win\n") ;
else printf("Bob will win\n") ;
}
return 0 ;}
#include<cstdlib>
int data[1001] ;
int cmp(const void *a, const void *b){
return *(int *)a < *(int *)b ? -1 : 1 ;
}
int main(){
int t, n, i, j, sum ;
scanf("%d", &t) ;
while(t--){
sum = 0 ;
scanf("%d", &n) ;
data[0] = 0 ;
for(i=1; i<=n; i++)
scanf("%d", &data[i]) ;
qsort(data, n+1, sizeof(data[0]), cmp) ;
for(i=n; i>0; i-=2)
sum ^= (data[i] - data[i-1] - 1) ;
if(sum) printf("Georgia will win\n") ;
else printf("Bob will win\n") ;
}
return 0 ;}