算法、博弈

这道题是一道比较绕的题,但只要把其中的逻辑关系搞明白了,问题就能迎刃而解,有两个注意点:

  • 调用递归,递归函数的好坏决定着算法成功与否(逻辑复杂)
  • 动态规划,空间换时间使得代码性能提升(不用动态规划只能通过数据量较小的30%的数据,也就是只能拿到30%的分数)
    取球博弈:

两个人玩取球的游戏。
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。
如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。
如果两人都是奇数,则为平局。

假设双方都采用最聪明的取法,
第一个取球的人一定能赢吗?
试编程解决这个问题。

输入格式:
第一行3个正整数n1 n2 n3,空格分开,表示每次可取的数目 (0<n1,n2,n3<100)
第二行5个正整数x1 x2 … x5,空格分开,表示5局的初始球数(0<xi<1000)

输出格式:
一行5个字符,空格分开。分别表示每局先取球的人能否获胜。
能获胜则输出+,
次之,如有办法逼平对手,输出0,
无论如何都会输,则输出-

static int[] a=new int[3];
	static char[][][] cache=new char[1000][2][2];//1奇0偶
	public static void main(String[] args) {
		Scanner reader=new Scanner(System.in);
		for(int i = 0;i<3;i++) {
			a[i]=reader.nextInt();
		}
		Arrays.sort(a);
		for(int i=0;i<5;i++) {
			System.out.print(test(reader.nextInt(),0,0)+" ");
		}
	}
	private static char test(int n, int me, int you) {
		if(n<a[0]) {
			if(me==1&&you==0)return '+';
			else if(me==0&&you==1) return '-';
			else return '0';
		}
		if(cache[n][me][you]!='\0')return cache[n][me][you];
		boolean res=false;
		for(int i=0;i<a.length;i++) {
			if(n<a[i])break;
			if(test(n-a[i],you,(me+a[i])&1)=='-') {
				cache[n][me][you]='+';
				return '+';
			}
			else if(test(n-a[i],you,(me+a[i])&1)=='0')res=true;
		}
		if(res) {cache[n][me][you]='0';return '0';}
		else {cache[n][me][you]='-';return '-';}
	}

首先是对题目的理解,对于任何选择,只要有一种能制胜,那就return ‘+’
如果不存在这种情况就看有没有逼平的局面,有->return ‘0’
else return ‘-’

然后是递归函数的理解,一开始是我选,结果如何取决于你选的结果。轮到你选的时候也调用同一个递归函数,所以又会回到我选,直到可以跳出函数,就可以知道结果。很多递归函数都是这样写,给一个动力,使其能够以函数的出口为方向。

如果有时间,可以考虑动态规划法。当表中有数据时,可以查表。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值