PREV-14高僧斗法(尼姆博弈)Java版,可能是全网最详解了

PREV-14高僧斗法(尼姆博弈)Java版,可能是全网最详解了

前言

高僧斗法,名字倒是挺有意思,大威天龙…这道题中涉及到了一个我从未接触到的知识,尼姆博弈,对于尼姆博弈,必须要知道奇异局势,以及怎么给对手造成奇异局势,我觉得看百度百科尼姆博弈应该就能明白这些了,知道这些就完全足够解决这道题了。好吧,现在来看看这道题。

问题描述

古时丧葬活动中经常请高僧做法事。仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛。
  节目大略步骤为:先用粮食(一般是稻米)在地上“画”出若干级台阶(表示N级浮屠)。又有若干小和尚随机地“站”在某个台阶上。最高一级台阶必须站人,其它任意。(如图1所示) ps:这也没图啊,蓝桥杯这个练习系统真狗。
  两位参加游戏的法师分别指挥某个小和尚向上走任意多级的台阶,但会被站在高级台阶上的小和尚阻挡,不能越过。两个小和尚也不能站在同一台阶,也不能向低级台阶移动。
  两法师轮流发出指令,最后所有小和尚必然会都挤在高段台阶,再也不能向上移动。轮到哪个法师指挥时无法继续移动,则游戏结束,该法师认输。
  对于已知的台阶数和小和尚的分布位置,请你计算先发指令的法师该如何决策才能保证胜出。

输入格式

输入数据为一行用空格分开的N个整数,表示小和尚的位置。台阶序号从1算起,所以最后一个小和尚的位置即是台阶的总数。(N<100, 台阶总数<1000)

输出格式

输出为一行用空格分开的两个整数: A B, 表示把A位置的小和尚移动到B位置。若有多个解,输出A值较小的解,若无解则输出-1。

样例输入

1 5 9

样例输出

1 4

样例输入

1 5 8 10

样例输出

1 3

代码

package lanqiao;

import java.util.Arrays;
import java.util.Scanner;

public class PREV_14 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner (System.in);
		String s=sc.nextLine();
		String  c[]=s.split(" ");
		int m[]=new int[c.length-1];
		for(int i=1;i<c.length;i++){
			m[i-1]=Integer.valueOf(c[i])-Integer.valueOf(c[i-1])-1;//得到每堆中的数量
		}
		//System.out.println(Arrays.toString(m));
		int sum=0;
		for(int i=0;i<m.length;i=i+2){//i=i+2,对应的是两两配对的数
			sum^=m[i];//进行异或操作
		}
		
		if(sum==0){//此时已经是奇异局势,我方必输,即无解的情况
			//System.out.println(-1);
		}
		else{//我方能够赢,根据题意,输出A较小的值,所有从最小的和尚开始,尝试进行操作,为对方造成奇异局势
			for(int i=0;i<c.length-1;i++){//从最开始的和尚开始
				for(int j=1;j+Integer.valueOf(c[i])<Integer.valueOf(c[i+1]);j++){//该和尚能走的所有情况
					//j对应的是走的步数,进行遍历
					m[i]-=j;//表示走了j步,然后再对剩下的所有数,进行异或操作
					if(i!=0){//表示不是第一个和尚了,即就是后面的和尚往后走了
						m[i-1]+=j;//那么前面的和尚能走的情况就多了
					}
					sum=0;
					for(int k=0;k<m.length;k=k+2){//对现在的情况进行异或操作
						sum^=m[k];
					}
					if(sum==0){
						System.out.println(c[i]+" "+(Integer.valueOf(c[i])+j));
						return;
					}
					//回溯
					m[i]+=j;
					if(i!=0){
						m[i-1]-=j;
					}
				}
			}
			
		}
	}

}

总结

代码是借鉴的别人的,我补了注释,网上的其他文章,对一些细节都直接一笔带过了,拿1,5, 8,10这个例子来说,1,5,8,10可分为三堆(3,2,1),但实际上分为两堆即为:(3,1),把1,5看成一对,8,10看成一对,那么5,8为什么不是一对呢,因为假如5,8是一对,5,8之间有2个距离,假设一法师动5,8之间的距离,那么另一法师可以移动距离变大了,也可以移到相同的距离,所以5,8之间的台阶对游戏是没有影响的,这是在总数只有三堆的情况下,如果有n堆,同理,中间的那些不是一对的,都对游戏无关,这也是为什么进行异或操作的循环,每次是加2了,具体如下图,这是随便编的一段样例在这里插入图片描述以上是个人拙见,有错误的地方还望指教。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值