AI刷题 No203 小Q和小X的游戏 | 豆包MarsCode AI刷题

47 阅读3分钟

刷题 No203 小Q和小X的游戏

问题描述

小Q和小X是很好的朋友,她们正在玩一个游戏。她们拿到了一个数组,游戏开始时小Q随机选择一个元素作为起点。接着,两人轮流行动,小Q先行动。

每次行动时,当前玩家需要选择当前元素左边比它更小的元素,然后移动到该元素,接下来换另一方从这个元素继续移动。如果某一方无法进行合法的移动,则该方输掉游戏。

小Q想知道,在双方都采取最优策略的情况下,她最终获胜的概率是多少?请输出分数的最简形式,即分子和分母互素。如果小Q必胜,则输出 1/1。如果小Q必败,则输出 0/1

问题分析

这道题的关键是分析游戏的状态,并通过动态规划和博弈论来求解。我们可以将问题看作一个“博弈”问题,其中每个元素表示一个“游戏状态”。两位玩家轮流从当前状态中选择一个更小的元素进行移动,直到某一方无法继续移动为止。要解决这个问题,我们需要判断每个状态(即数组中的每个元素)是否是“赢”的状态还是“输”的状态,最终通过动态规划得到小Q的胜率。

解题思路

1、状态定义

  • 定义每个元素为一个状态,数组中每个位置的元素都对应一个可能的游戏状态。
  • 小Q和小X轮流选择一个比当前元素小的元素作为下一步的移动目标。如果当前元素的左边没有比它小的元素可选,那么当前玩家就输掉了。

2、胜负状态判断

  • 每个状态有两种可能:胜利状态(Win)和失败状态(Lose)。当轮到玩家进行决策时,如果他能选择一个使对方必败的状态,那么当前状态就是胜利状态。反之,如果每个选择都会让对方进入胜利状态,则当前状态就是失败状态。

3、动态规划

  • dp[i] 表示从数组第 i 个位置开始,当前玩家能否必胜。如果 dp[i] = true,表示从位置 i 开始当前玩家必胜;如果 dp[i] = false,表示从位置 i 开始当前玩家必败。
  • 状态转移:对于每个位置 i,如果存在一个位置 j(在 i 之前且 nums[j] < nums[i])使得 dp[j] = false,即可以强制对方进入一个必败状态,那么 dp[i] = true
  • 初始状态:如果当前位置没有比它小的元素,那么 dp[i] = false,即当前玩家必败
  • 最后:统计所有小Q能胜的初始位置,然后输出胜率。

示例代码

 public static String solution(int n, int[] a) {
         // dp数组,dp[i]表示从位置i出发当前玩家是否必胜
         boolean[] dp = new boolean[n];
 ​
         // 反向遍历数组,从后往前处理dp值
         for (int i = n - 1; i >= 0; i--) {
             // 判断当前位置是否有比当前元素小的左边元素
             boolean canWin = false;
             for (int j = i - 1; j >= 0; j--) {
                 if (a[j] < a[i] && !dp[j]) {
                     // 如果可以跳到一个对方必败的状态
                     canWin = true;
                     break;
                 }
             }
             dp[i] = canWin;
         }
 ​
         // 计算小Q的胜率
         int winCount = 0;
         for (int i = 0; i < n; i++) {
             if (dp[i]) {
                 winCount++;
             }
         }
 ​
         // 输出最简分数
         int gcd = gcd(winCount, n);
         String result = winCount / gcd + "/" + n / gcd;
         return result;
     }
 ​
 // 求最大公约数
     public static int gcd(int a, int b) {
         while (b != 0) {
             int temp = a % b;
             a = b;
             b = temp;
         }
         return a;
     }