Leetcode.486 预测赢家

题目链接

Leetcode.486 预测赢家 mid

题目描述

给你一个整数数组 nums 。玩家 1 1 1 和玩家 2 2 2 基于这个数组设计了一个游戏。

玩家 1 1 1 和玩家 2 2 2 轮流进行自己的回合,玩家 1 1 1 先手。开始时,两个玩家的初始分值都是 0 0 0 。每一回合,玩家从数组的任意一端取一个数字(即, n u m s [ 0 ] nums[0] nums[0] n u m s [ n u m s . l e n g t h − 1 ] nums[nums.length - 1] nums[nums.length1]),取到的数字将会从数组中移除(数组长度减 1 1 1 )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。

如果玩家 1 1 1 能成为赢家,返回 true 。如果两个玩家得分相等,同样认为玩家 1 1 1 是游戏的赢家,也返回 true 。你可以假设每个玩家的玩法都会使他的分数最大化。

示例 1:

输入:nums = [1,5,2]
输出:false
解释:一开始,玩家 1 可以从 1 和 2 中进行选择。
如果他选择 2(或者 1 ),那么玩家 2 可以从 1(或者 2 )和 5 中进行选择。如果玩家 2 选择了 5 ,那么玩家 1 则只剩下 1(或者 2 )可选。
所以,玩家 1 的最终分数为 1 + 2 = 3,而玩家 2 为 5 。
因此,玩家 1 永远不会成为赢家,返回 false 。

示例 2:

输入:nums = [1,5,233,7]
输出:true
解释:玩家 1 一开始选择 1 。然后玩家 2 必须从 5 和 7 中进行选择。无论玩家 2 选择了哪个,玩家 1 都可以选择 233 。
最终,玩家 1(234 分)比玩家 2(12 分)获得更多的分数,所以返回 true,表示玩家 1 可以成为赢家。

提示:

  • 1 ≤ n u m s . l e n g t h ≤ 20 1 \leq nums.length \leq 20 1nums.length20
  • 0 ≤ n u m s [ i ] ≤ 1 0 7 0 \leq nums[i] \leq 10^7 0nums[i]107

解法:记忆化搜索

我们定义 d f s ( i , j ) dfs(i,j) dfs(i,j)当前先手 处于 ( i , j ) (i,j) (i,j) 的局面,所能获得的最大的分。

  • 当前先手 选择 n u m s [ i ] nums[i] nums[i] 就会使得后手处于 ( i + 1 , j ) (i + 1,j) (i+1,j) 局面,即后手的最大得分为 d f s ( i + 1 , j ) dfs(i + 1,j) dfs(i+1,j)
  • 当前先手 选择 n u m s [ j ] nums[j] nums[j] 就会使得后手处于 ( i , j − 1 ) (i ,j - 1) (i,j1) 局面,即后手的最大得分为 d f s ( i , j − 1 ) dfs(i ,j - 1) dfs(i,j1)

先手要让后手得分尽可能的小,所以先手直接让后手选择较小的那个得分,即 m i n { d f s ( i + 1 , j ) , d f s ( i , j − 1 ) } min\{ dfs(i + 1,j),dfs(i ,j - 1)\} min{dfs(i+1,j),dfs(i,j1)}

因为无论怎么选择,先手后手得分总和是相同的。所以,后手的得分已经确定,那么此时先手的得分为 s u m ( i , j ) − m i n { d f s ( i + 1 , j ) , d f s ( i , j − 1 ) } sum(i,j) - min\{ dfs(i + 1,j),dfs(i ,j - 1)\} sum(i,j)min{dfs(i+1,j),dfs(i,j1)}

i = j i = j i=j 时,此时先手只能选择 n u m s [ i − 1 ] nums[i-1] nums[i1](下标从 1 1 1 开始)。

最后我们只需要判断 d f s ( 1 , n ) dfs(1,n) dfs(1,n) 是否大于总分 s u m ( 1 , n ) sum(1,n) sum(1,n) 的一半,即 d f s ( 1 , n ) × 2 ≥ s u m ( 1 , n ) dfs(1,n) \times 2 \geq sum(1,n) dfs(1,n)×2sum(1,n)

时间复杂度: O ( n 2 ) O(n^2) O(n2)

C++代码:文章来源地址https://uudwc.com/A/Gd2Nz

class Solution {
public:
    bool predictTheWinner(vector<int>& nums) {
        int n = nums.size();
        vector<int> s(n + 1);
        for(int i = 1;i <= n;i++) s[i] = s[i - 1] + nums[i - 1];

        auto get = [&](int l,int r)->int{
            return s[r] - s[l - 1];
        };

        int f[n + 1][n + 1];
        memset(f,-1,sizeof f);

        function<int(int,int)> dfs = [&](int i,int j)->int{
            if(f[i][j] != -1) return f[i][j];
            if(i == j){
                f[i][j] = nums[i - 1];
                return f[i][j];
            }

            f[i][j] = get(i,j) - min(dfs(i + 1,j),dfs(i,j - 1));

            return f[i][j];
        };

        return dfs(1,n) * 2 >= get(1,n);
    }
};

原文地址:https://blog.csdn.net/m0_74396439/article/details/132951043

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年09月18日 03:23
GFS分布式存储
下一篇 2023年09月18日 03:23