HDU4315 Climbing the Hill
题目链接:https://cn.vjudge.net/problem/HDU-4315
知识点: 博弈论
题目大意:
\(Alice\) 和 \(Bob\) 轮流指挥 \(N\) 个人爬山,这 \(N\)个人在山顶下的不同层,国王是第 \(k\) 个人。山的每一层都最多只能容纳 \(1\) 个人(除了山顶),两个玩家每次都能指挥任意一个人向上爬任意层直到山顶,但不能让一个人越过另一个人。指挥国王爬到山顶上即可获胜。
解题思路:
首先,如果国王是第一个人,先手必胜。
如果 \(N\) 是偶数,关键局面为:对于所有合法的 \(i\),有第 \(2i\) 个人和第 \(2i-1\) 个人相邻。易知此时当国王是第偶数个人时后手必胜,因为无论先手怎么操作,后手都至少能维持住这个局面,或者取得胜利;当国王是第奇数个人时也是后手必胜,后手可以维持这个关键局面直到国王成为第 \(3\) 个人,并继续保持第 \(2i-1\) 和第 \(2i\) 相邻,先手接下来迟早会被迫将第一个人移到山顶,后手下一步将第二个人移到山顶的下一个位置,这是一个后手必胜的局面。现在游戏已经转换成一个 \(Nim\) 博弈,石子就是第 \(2i-1\) 和第 \(2i\) 个人之间的间隔。
如果 \(N\) 是奇数,可以在第一个人前面再想象一个人,他在山顶的再上一层,当第一个人被放到山顶的时候,二者相邻,此时又转换成偶数个人的情况了。有一种特殊情况是当国王是第二个人的时候,那么想象出来的这个人就得放在山顶,当第一个人被放到山顶的下一层时二者即可相邻,因为先手如果将第一个人直接放到山顶,那么后手能直接取胜。
AC代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int maxn=1005; 5 int pos[maxn]; 6 int main(){ 7 int N,k; 8 while(scanf("%d%d",&N,&k)==2){ 9 for(int i=1;i<=N;i++) scanf("%d",&pos[i]); 10 if(k==1){ 11 printf("Alice\n"); 12 continue; 13 } 14 if(N%2==0){ 15 int sg=0; 16 for(int i=1;i<=N;i+=2) 17 sg^=(pos[i+1]-pos[i]-1); 18 if(!sg) printf("Bob\n"); 19 else printf("Alice\n"); 20 } 21 else{ 22 int sg=pos[1]; 23 if(k==2) sg--; 24 for(int i=2;i<=N;i+=2) 25 sg^=(pos[i+1]-pos[i]-1); 26 if(!sg) printf("Bob\n"); 27 else printf("Alice\n"); 28 } 29 } 30 return 0; 31 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”