【蓝桥杯】取球博弈(dp+深搜+博弈)

转载几种经典博弈算法

题目描述

取球博弈

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

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

输入格式:

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

输出格式:

一行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.csdn.net/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

你可能感兴趣的:(蓝桥杯)