当前位置: 首页 > news >正文

蓝桥杯 取球博弈

取球博弈

原题目链接

题目描述

两个人玩取球的游戏。

一共有 N 个球,每人轮流取球,每次可取集合 n₁, n₂, n₃ 中的任何一个数目。

如果无法继续取球,则游戏结束。

此时,持有奇数个球的一方获胜。

如果两人都是奇数,则为平局。

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


输入描述

输入格式:

第一行 3 个正整数 n₁, n₂, n₃
(0 < n₁, n₂, n₃ < 100),空格分开,表示每次可取的数目。

第二行 5 个正整数 x₁, x₂, ⋯, x₅
(0 < xᵢ < 1000),空格分开,表示 5 局的初始球数。


输出描述

输出一行 5 个字符,空格分开。

分别表示每局先取球的人能否获胜。

  • 能获胜则输出 +
  • 如有办法逼平对手,输出 0
  • 无论如何都会输,则输出 -

输入输出样例

输入

1 2 3
1 2 3 4 5

输出

+ 0 + 0 -

c++代码

#include<bits/stdc++.h>using namespace std;unordered_map<string, string> mp;
vector<int> arr(3);int x, n1, n2, n3;string dfs(int a, int b) {string str = to_string(x) + " " + to_string(a % 2) + " " + to_string(b % 2);if (mp.find(str) != mp.end()) return mp[str];if (x < arr[0]) {if (a % 2 != 0 && b % 2 == 0) {mp[str] = "+"; return "+";}else if (a % 2 == 0 && b % 2 != 0) {mp[str] = "-"; return "-";}else return "0";}string sym = "-";for (int i = 0; i < 3; i++) {if (x < arr[i]) break;x -= arr[i];a += arr[i];string op = dfs(b, a);x += arr[i];a -= arr[i];if (op == "-") {mp[str] = "+"; return "+";}else if (op == "0") sym = "0";}mp[str] = sym;return sym;
}int main() {for (int i = 0; i < 3; i++) cin >> arr[i];sort(arr.begin(), arr.end());for (int i = 0; i < 5; i++) {cin >> x;if (i != 4) cout << dfs(0, 0) << " ";else cout << dfs(0, 0) << endl;}return 0;
}

题解

博弈论(递归+回溯)

定义string dfs(int a, int b)的返回值为剩余球数n,先取秋的人的当前球数a,后取球的人的当前球数b的局面情况。

如果当前剩余球数x小于n1,n2,n3的最小值,则无法继续取球,游戏结束。结算胜负。

if (x < arr[0]) {//我对arr排序了,所以第一个就是最小的。if (a % 2 != 0 && b % 2 == 0) return "+";else if (a % 2 == 0 && b % 2 != 0) return "-";else return "0";
}

我们枚举先取球的人可以取出的球数

x -= arr[i];
a += arr[i];

然后我们调用dfs(b, a)得出敌方的局面。

如果敌方必输,那么我们必赢。

如果敌方必赢,也不能说我们必输,因为我们可以不取这个数量的球,可以换个数量试试。

但是如果不管我们取什么数量的球,敌方的局面都是必赢,那么我们才是必输。

如果敌方平局,且敌方没有必输的情况,那么我们最好的局面也是平局。

string sym = "-";
for (int i = 0; i < 3; i++) {if (x < arr[i]) break;x -= arr[i];a += arr[i];string op = dfs(b, a);x += arr[i];a -= arr[i];if (op == "-") return "+"; //如果敌方必输,那么我们必赢。else if (op == "0") sym = "0";//如果敌方平局,且敌方没有必输的情况,那么我们最好的局面也是平局。
}
return sym;//不管我们取什么数量的球,敌方的局面都是必赢,那么我们才是必输。

记忆化搜索

一局的胜负由,剩余球数n,先取秋的人的当前球数a的奇偶性,后取球的人的当前球数b的奇偶性共同决定。

我们用字符串str存储这种情况,用mp存储这种情况的局面。

string str = to_string(x) + " " + to_string(a % 2) + " " + to_string(b % 2);
unordered_map<string, string> mp;

当我们再次碰到相同的局面我们直接返回存储好的值,而不是重复同样的dfs(a, b),省下很多时间。

if (mp.find(str) != mp.end()) return mp[str];
http://www.dtcms.com/a/466145.html

相关文章:

  • 怀化百度整站优化服务弹窗网站制作
  • 做外国美食的视频网站云服务器 多个网站
  • 工业设备预测性维护:能源成本降低的“隐藏钥匙”?
  • STM32F103RCT6+STM32CubeMX+keil5(MDK-ARM)+Flymcu完成固定长度的数据的收发
  • 5. React中的组件:组件是什么;React定义组件
  • 三十、钙钛矿量子点专业词汇(我爱钙钛矿)
  • 云手机 流畅运行
  • 从 “跨域报错到彻底解决”:Spring Boot+Security+JWT 实战踩坑指南
  • 嵌入模型蓝图与扫盲
  • 中核华泰建设有限公司网站小游戏网站网址
  • 做网站技术服务费属于什么科目做ppt好用的网站有哪些
  • 简单网站建设方案icp备案查询官方网站
  • Python中内置的常用装饰器
  • 年度进化挑战:从“前端实现者”到“智能体协作者”与“复杂问题定义者”
  • 靠谱的CC公益站
  • 做网站哪家便宜如何做企业招聘网站
  • HI3798MV100 运营商机顶盒NAS LINUX OS - IP地址静态绑定指南
  • 外贸网站建设公司价格湛江建站程序
  • 第三章:字符串增强与模板字符串
  • 网站开发建设技术规范书没经验可以做电商运营吗
  • Jira:设置语言 / 创建史诗 / 创建冲刺 / 创建问题
  • CancellationToken与Abort
  • linux达梦数据库操作
  • [自荐]一款mac电脑历史剪切板工具,类似著名的Paste
  • 二级域名可以做不同的网站吗网站建设网络推广广告语
  • MapReduce简介
  • FreeType 2.7 – 卓越的 Linux 字体质量
  • 龙江建站技术wordpress 管理 主题
  • 企业网站建设 制作网站建设基本流程流程图
  • 【Homebrew安装 MySQL 】macOS 用 Homebrew 安装 MySQL 完整教程