高僧斗法
Posted mabeytang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高僧斗法相关的知识,希望对你有一定的参考价值。
问题描述
古时丧葬活动中经常请高僧做法事。仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛。
节目大略步骤为:先用粮食(一般是稻米)在地上“画”出若干级台阶(表示N级浮屠)。又有若干小和尚随机地“站”在某个台阶上。最高一级台阶必须站人,其它任意。(如图1所示)
两位参加游戏的法师分别指挥某个小和尚向上走任意多级的台阶,但会被站在高级台阶上的小和尚阻挡,不能越过。两个小和尚也不能站在同一台阶,也不能向低级台阶移动。
两法师轮流发出指令,最后所有小和尚必然会都挤在高段台阶,再也不能向上移动。轮到哪个法师指挥时无法继续移动,则游戏结束,该法师认输。
对于已知的台阶数和小和尚的分布位置,请你计算先发指令的法师该如何决策才能保证胜出。
节目大略步骤为:先用粮食(一般是稻米)在地上“画”出若干级台阶(表示N级浮屠)。又有若干小和尚随机地“站”在某个台阶上。最高一级台阶必须站人,其它任意。(如图1所示)
两位参加游戏的法师分别指挥某个小和尚向上走任意多级的台阶,但会被站在高级台阶上的小和尚阻挡,不能越过。两个小和尚也不能站在同一台阶,也不能向低级台阶移动。
两法师轮流发出指令,最后所有小和尚必然会都挤在高段台阶,再也不能向上移动。轮到哪个法师指挥时无法继续移动,则游戏结束,该法师认输。
对于已知的台阶数和小和尚的分布位置,请你计算先发指令的法师该如何决策才能保证胜出。
输入格式
输入数据为一行用空格分开的N个整数,表示小和尚的位置。台阶序号从1算起,所以最后一个小和尚的位置即是台阶的总数。(N<100, 台阶总数<1000)
输出格式
输出为一行用空格分开的两个整数: A B, 表示把A位置的小和尚移动到B位置。若有多个解,输出A值较小的解,若无解则输出-1。
样例输入
1 5 9
样例输出
1 4
样例输入
1 5 8 10
样例输出
1 3
View Code
Algorithm
这个题目看了很久想不到方法,看了下提示,要用到博弈论的知识,而且还是Nim游戏,因此特意学习了Nim游戏:传送门~
我觉得我不能讲的比他还要好了^_^,感谢一下博主。
这个题目我们转化一下,就成了Nim游戏。
将小和尚两两分组,就像这样:
值得注意的一点是,区间间隔可能会增加,也可能会减少。
AC
1 /* 2 * 博弈论 3 * 尼姆博弈 - Nim 4 * 再此警告一下一下自己啊, 千万不要用 new 来分配内存 5 * 不然怎么错的都不知道...... 6 * 内存泄漏会导致返回值不一定为 0 7 * 但是比赛必须为 0 8 */ 9 #include<iostream> 10 #include<string> 11 #include<sstream> 12 #include<cstdio> 13 14 using namespace std; 15 16 void fun(int *a, int n) 17 { 18 int x[109] = {0}; 19 int k = 0, mx = 0, loc = 0; 20 for(int i=1;i<n;i+=2) 21 x[k++] = a[i] - a[i-1] - 1; 22 int t = 0; 23 for(int i=0;i<k;i++){ 24 t ^= x[i]; 25 } 26 if(!t){ // 平衡态先手必输 27 cout<<-1<<‘ ‘; 28 return; 29 } 30 int temp = 0; 31 for(int j=0;j<n;j++){ 32 for(int k=a[j]+1;k<a[j+1];k++){ 33 if(j&1){ // 增大间距 34 if(!(t^x[j>>1]^(k-a[j-1]-1))){ 35 printf("%d %d ", a[j], k); 36 return; 37 } 38 } 39 else{ // 缩小间距 40 if(!(t^x[j>>1]^(a[j+1]-k-1))){ 41 printf("%d %d ", a[j], k); 42 return; 43 } 44 } 45 } 46 } 47 /* 48 for(int j=0;j<k;j++) 49 cout<<x[j]<<‘ ‘; 50 */ 51 } 52 53 int main() 54 { 55 string s; 56 while(getline(cin, s)) 57 { 58 stringstream ss(s); 59 int x = 0, i = 0; 60 int a[109] = {0}; 61 while(ss>>a[i++]); 62 ss.clear(); 63 fun(a, i-1); 64 /* 65 for(int j=0;j<i-1;j++) 66 cout<<a[j]<<‘ ‘; 67 cout<<‘ ‘; 68 */ 69 } 70 71 return 0; 72 }
2019-02-26
22:04:08
以上是关于高僧斗法的主要内容,如果未能解决你的问题,请参考以下文章