一、题目
A、B两个人玩抢7游戏,游戏规则为:
A先报一个起始数字 X(10 ≤ 起始数字 ≤ 10000),B报下一个数字 Y (X - Y < 3),A再报一个数字 Z(Y - Z < 3),以此类推,直到其中一个抢到7,抢到7即为胜者;
在B赢得比赛的情况下,一共有多少种组合?
二、输入
起始数字 M (10 ≤ M ≤ 10000)
三、输出
B能赢得比赛的组合次数
四、示例
输入
10
输出
1
说明:B只有一种赢的组合,A起始选择10,B接着选择9,A接着选择8,B接着选择7赢得胜利。
五、题解
- 本题是爬楼梯问题的一个变种。爬楼梯是从从下往上,每次跳1层或者2层,到第n层的选择次数。本题包括2个人比赛,从上往下跳,每次基于对方当前层数跳1层或者2层
- 每次选择不是基于最优选择的博弈思维,而是枚举所有可能组合数
- 动态规划问题一般和求最值联系在一起,本题和爬楼梯问题解法一样,把求组合数理解为最大可能的组合
5.1 Java 实现
package org.stone.study.algo.ex202412;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
/**
* 抢7问题:A、B两个人玩抢7游戏,游戏规则为:
*
* A先报一个起始数字 X(10 ≤ 起始数字 ≤ 10000),B报下一个数字 Y (X - Y < 3),A再报一个数字 Z(Y - Z < 3),以此类推,直到其中一个抢到7,抢到7即为胜者;
*
* 在B赢得比赛的情况下,一共有多少种组合?
*/
public class BeFirst7 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 10
int m = sc.nextInt();
BigInteger ans = getCount(m);
// 1
System.out.println(ans);
}
public static BigInteger getCount(int m) {
// dpA[i]表示A到i的总的走法数
BigInteger[] dpA = new BigInteger[m + 2];
// dpB[i]表示B到i的总的走法数
BigInteger[] dpB = new BigInteger[m + 2];
Arrays.fill(dpA, BigInteger.ZERO);
Arrays.fill(dpB, BigInteger.ZERO);
// A到m的走法总数,A先走到m
dpA[m] = BigInteger.ONE;
for(int i = m - 1; i > 6; i--) {
// B到i的走法数,基于A的走法数(跳1或者2步)
dpB[i] = dpA[i + 1].add(dpA[i + 2]);
dpA[i] = dpB[i + 1].add(dpB[i + 2]);
}
return dpB[7];
}
}
5.2 Python实现
# A 从m(m >= 10)开始,B到达7的走法总数。A和B每次往下走1或者2步
def getCount(m):
dp_a = [0] * (m + 2)
dp_b = [0] * (m + 2)
dp_a[m] = 1
for i in range(m - 1, 6, -1):
dp_b[i] = dp_a[i + 1] + dp_a[i + 2]
dp_a[i] = dp_b[i + 1] + dp_b[i + 2]
return dp_b[7]
if __name__ == '__main__':
m = int(input())
res = getCount(m)
print(res)