头像

Cyan

四川成都

深度强化学习炼丹师

2012年第三届蓝桥杯省赛-J.取球游戏

2012年第三届蓝桥杯省赛-J.取球游戏

2021-12-02 · 181次阅读 · 原创 · 数据结构与算法

原题链接

题面

今盒子里有 n 个小球,A、B 两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断。

我们约定:

每个人从盒子中取出的球的数目必须是:1,3,7 或者 8 个。轮到某一方取球时不能弃权!A 先取球,然后双方交替取球,直到取完。被迫拿到最后一个球的一方为负方(输方)

请编程确定出在双方都不判断失误的情况下,对于特定的初始球数,A 是否能赢?

输入描述

先是一个整数 n (n<100),表示接下来有 n 个整数。

然后是 n 个整数,每个占一行(每个整数 < 104),表示初始球数。

输出描述

程序则输出 n 行,表示 A 的输赢情况(输为 0,赢为 1)。

输入样例

4
1
2
10
18

输出样例

0
1
1
0

题解

动态规划,博弈论

由题,拿走最后一个的人为输家,令 f[i] 表示有 i 个球的时候 A 先手并采取最优策略的胜负情况 。

对于一个状态 f[i] ,其获胜的的条件是 f[i - 1]f[i - 3]f[i - 7]f[i - 8] 中有一个状态为输 ,即只要先手的人拿走球后只要出现必败的状态给后手,则先手必赢。

代码

#include<bits/stdc++.h> using namespace std; const int N = 1e4 + 5; int T, n, a[4] = {1, 3, 7, 8}; bool f[N]; int main() { f[1] = false; for (int i = 2; i <= 10000; i++) { for (int j = 0; j < 4; j++) { if (i > a[j] && !f[i - a[j]]) f[i] = true; } } cin >> T; while (T--) { cin >> n; if (f[n]) puts("1"); else puts("0"); } return 0; }

标题: 2012年第三届蓝桥杯省赛-J.取球游戏
链接: https://www.fightingok.cn/detail/158
更新: 2022-09-18 22:43:56
版权: 本文采用 CC BY-NC-SA 3.0 CN 协议进行许可