点击查看:蓝桥杯历年真题 题解目录
取球博弈
下面有两段代码:
第一段代码: 思路清晰,未进行优化,只能得一部分分数
第二段代码: 在第一段代码的基础上采用记忆性递归,降低复杂度。
第一段代码的思路:
1. 利用递归求解
2. 递归出口,n<a[0] 即:石头数目小于可以取得的数目,停止递归
当A方 为奇数,B方为 偶数时, A方胜出。
当B方 为奇数,A方为 偶数时, B方胜出
其余为平局。
3. 在 n>a[i]的条件下,执行递归
如果存在递归返回 '-' 则A方获胜返回 '+'
引入 平局变量 pingju: 默认为false;
如果 有 "平局" 的情况 pingju = true;
在不获胜,即仍能继续执行的情况下,判断是否存在平局
if(存在平局) return '0' ; else return '-';
package java_B_2016;
import java.util.Arrays;
import java.util.Scanner;
public class Main009_取球博弈2 {
static int []a = new int[3];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
for(int i=0;i<3;i++) {
a[i]=in.nextInt();
}
Arrays.sort(a);
for(int i=0;i<5;i++) {
int n = in.nextInt();
char res = f(n,0,0);
System.out.print(res+" ");
}
}
/**
* @param n 球的总数目
* @param me 我方持有的数目-->我方数目的奇偶性
* @param you 对手持有的数目-->我方数目的奇偶性
* @return
*/
private static char f(int n, int me, int you) {
if(n<a[0]) { // n<a[0] 即双方没有了可取的情况,游戏结束 即递归出口
if((me&1)==1 && (you&1)==0) return '+';
if((me&1)==0 && (you&1)==1) return '-';
else return '0';
}
boolean pingju = false;
for(int i=0;i<3;i++) {
if(n>=a[i]) {
char res = f(n-a[i], you, me+a[i]);// 注意此处的 me 和 you交换了位置
if(res=='-')
return '+';
if(res == '0')
pingju=true;
}
}
// 如果程序走到这一行,说明不存在对手输的情况,那么是否存在平局的情况
if(pingju) return '0';
else return '-';
}
}
下段代码,是对上段代码的优化
记忆性递归:
package java_B_2016;
import java.util.Arrays;
import java.util.Scanner;
public class Main009_取球博弈3 {
private static int[] n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = new int[3];
for(int i = 0; i < 3; i++) {
n[i] = sc.nextInt();
}
Arrays.sort(n);//排序
for (int i = 0; i < 5; i++) {
int num = sc.nextInt();
char res = f(num, 0, 0);
System.out.print(res + " ");
}
System.out.println();
}
static char[][][]cache = new char[1000][2][2];
/**
* 参数代表着当前取球人面临的局面
* @param num 球的总数
* @param me 我方持有的数目-->我方数目的奇偶性
* @param you 对手持有的数目-对方数目的奇偶性
* @return
*/
private static char f(int num, int me, int you) {
if (num<n[0]){
if ((me&1)==1&&(you&1)==0)return '+';
else if ((me&1)==0&&(you&1)==1)return '-';
else return '0';
}
if (cache[num][me][you]!='\0')return cache[num][me][you];
boolean ping = false;
for (int i = 0; i < 3; i++) {
if (num >= n[i]) {
char res = f(num - n[i], you, (n[i]&1)==0?me:(1-me));//注意此处,传递me和you的奇偶性
if (res == '-')
{
cache[num][me][you]='+';
return '+';
}
if (res == '0')
ping = true;
}
}
//如果能走到第这行,说明不存在对手输的情况,那么是否存在平的情况
if (ping){
cache[num][me][you]='0';
return '0';
}else{
cache[num][me][you]='-';
return '-';
}
}
}