题目描述
取球博弈
两个人玩取球的游戏。
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。
如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。
如果两人都是奇数,则为平局。
假设双方都采用最聪明的取法,
第一个取球的人一定能赢吗?
试编程解决这个问题。
输入格式:
第一行3个正整数n1 n2 n3,空格分开,表示每次可取的数目 (0<n1,n2,n3<100)
第二行5个正整数x1 x2 … x5,空格分开,表示5局的初始球数(0<xi<1000)
输出格式:
一行5个字符,空格分开。分别表示每局先取球的人能否获胜。
能获胜则输出+,
次之,如有办法逼平对手,输出0,
无论如何都会输,则输出-
例如,输入:
1 2 3
1 2 3 4 5
程序应该输出:
- 0 + 0 -
再例如,输入:
1 4 5
10 11 12 13 15
程序应该输出:
0 - 0 + +
再例如,输入:
2 3 5
7 8 9 10 11
程序应该输出:
- 0 0 0 0
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 3000ms
代码
转载自https://blog.youkuaiyun.com/lynn_coder/article/details/79602135
import java.util.*;
public class Main {
public static int ns[]=new int[3];//可取数目
public static int xs[]=new int[5];//初始的球数
static char dp[][][]=new char[2][1000][1000];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
for(int i=0;i<3;i++)
{
ns[i]=in.nextInt();
}
for(int i=0;i<5;i++)
{
xs[i]=in.nextInt();
}
int k;
for(int i=0;i<5;i++)
{
dp=new char[2][1000][1000];
k=dfs(0,0,0,xs[i]);
System.out.print((char)k+" ");
}
}
public static int min(int a[])
{
int min=9999;
for(int i:a)
{
if(min>i)
{
min=i;
}
}
return min;
}
public static char dfs(int p,int a,int b,int num)
{
int min=min(ns);//取可取球的最小值
int rest=num-a-b;//当前剩下的球的数量
if(dp[p][a][b]!='\u0000')//java当中的char类型如果没有初始化就是此字符,即一个空格
{
return dp[p][a][b];//已经初始化过,直接返回即可
}
if(rest<min)//如果当前剩余的不能满足取的条件
{
if(a%2==1&&b%2==0)
dp[p][a][b]='+';
else if(a%2==0&&b%2==1)
dp[p][a][b]='-';
else
dp[p][a][b]='0';
return dp[p][a][b];
}
if(p==0)//如果轮到a取球
{
int flag=0;//判断是否有和的可能
for(int i=0;i<3;i++)
{
if(rest>=ns[i])//如果可以取
{
if(dfs(1,a+ns[i],b,num)=='+')
return dp[0][a][b]='+';
else if(dfs(1,a+ns[i],b,num)=='0')
flag=1;
}
}
if(flag==1)
dp[0][a][b]='0';
else
dp[0][a][b]='-';
}
if(p==1)//如果是b取球
{
int flag=0;
for(int i=0;i<3;i++)
{
if(rest>=ns[i])//如果可以取
{
if(dfs(0,a,b+ns[i],num)=='-')
return dp[1][a][b]='-';
else if(dfs(0,a,b+ns[i],num)=='0')
flag=1;
}
}
if(flag==1)
dp[1][a][b]='0';
else
dp[1][a][b]='+';
}
return dp[p][a][b];
}
}
很奇怪的是在本地运行显示
但是在c语言网可以ac