蓝桥杯---取球博弈---DFS+记忆化---C++

31 篇文章 1 订阅
6 篇文章 0 订阅

问题描述

两个人玩取球的游戏。
一共有N个球,每人轮流取球,每次可取集合{n1,n2,n3}中的任何一个数目。
如果无法继续取球,则游戏结束。
此时,持有奇数个球的一方获胜。
如果两人都是奇数,则为平局。
假设双方都采用最聪明的取法,
第一个取球的人一定能赢吗?
试编程解决这个问题。

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

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

输入例子 1

1 2 3
1 2 3 4 5

输出例子 1

+ 0 + 0 -

输入例子 2

1 4 5
10 11 12 13 15

输出例子 2

0 - 0 + +

输入例子 3

2 3 5

输出例子 3

7 8 9 10 11
+ 0 0 0 0

提示
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 3000ms

实现思路

深搜 + 记忆化, 每个人都是最优解 = 优先考虑赢的情况, 其次考虑平的情况, 再其次才是输。

实现代码

#include<iostream>
#include<algorithm>
using namespace std;

const int SIZE = 1e3 + 5;

int dp[SIZE][2][2];
int a[3];

int dfs(int now, int nowplayer, int otherplayer) {
	if (dp[now][nowplayer][otherplayer]) {
		return dp[now][nowplayer][otherplayer];
	}

	if (now < a[0]) {
		if ((nowplayer & 1) == (otherplayer & 1)) return -1;	//平
		if (nowplayer & 1) return 1;							//胜
		return 2;												//负
	}

	else {
		bool noplayerwin = false;
		for (int i = 2; i >= 0; i--) {
			if (a[i] > now) continue;
			else {
				int otherresult = dfs(now - a[i], otherplayer, (nowplayer + a[i]) & 1);
				if (otherresult == 2) return dp[now][nowplayer][otherplayer] = 1;
				if (otherresult == -1) noplayerwin = true;
			}
		}
		if (noplayerwin) return dp[now][nowplayer][otherplayer] = -1;
		return dp[now][nowplayer][otherplayer] = 2;
	}
}


int main() {
	int maxnum;
	memset(dp, 0, sizeof(dp));
	cin >> a[0] >> a[1] >> a[2];
	sort(a, a + 3);
	for (int i = 1; i <= 5; i++) {
		cin >> maxnum;
		switch (dfs(maxnum, 0, 0))
		{
		case  1: cout << "+ "; break;
		case  2: cout << "- "; break;
		case -1: cout << "0 "; break;
		}
	}
	return 0;
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值