zoukankan      html  css  js  c++  java
  • 877. 石子游戏

    题干

    亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] 。游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。亚历克斯和李轮流进行,亚历克斯先开始。 每回合,玩家从行的开始或结束处取走整堆石头。 这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。假设亚历克斯和李都发挥出最佳水平,当亚历克斯赢得比赛时返回 true ,当李赢得比赛时返回 false 。

      

    示例:

    输入:[5,3,4,5]

    输出:true

    解释:

    亚历克斯先开始,只能拿前 5 颗或后 5 颗石子 。

    假设他取了前 5 颗,这一行就变成了 [3,4,5] 。

    如果李拿走前 3 颗,那么剩下的是 [4,5],亚历克斯拿走后 5 颗赢得 10 分。

    如果李拿走后 5 颗,那么剩下的是 [3,4],亚历克斯拿走后 4 颗赢得 9 分。

    这表明,取前 5 颗石子对亚历克斯来说是一个胜利的举动,所以我们返回 true 。

     

    提示:

    2 <= piles.length <= 500

    piles.length 是偶数。

    1 <= piles[i] <= 500

    sum(piles) 是奇数。

    来源:力扣(LeetCode)

    链接:https://leetcode-cn.com/problems/stone-game

     

    思路

    ①定义dp数组

    根据题意:每回合,玩家从行的开始或结束处取走整堆石头,因此石头对数组只能取开头或者结尾。

    dp[i][j]表示剩下的石头堆从第i堆到第j堆时本轮玩家相对于对方玩家多的石头数量,因此每轮的玩家都希望自己这一轮的dp[i][j]尽可能大于对方

    ②确定递推公式

    已知piles[0]=dp[0][0]、piles[1]=dp[1][1]

    如何得到dp[0][1]

    如果只有一堆石头,p1先手选dp[0][0]

    如果有两堆石头piles[0]和piles[1],当p1选择了之后p2就会选之前p1的策略

    piles[0]-dp[1][1]表示p1先手选了第一堆石头后,p2的最佳策略是选择第二堆石头

    piles[1]-dp[0][0]表示p1先手选了第二堆石头后,p2的最佳策略是选择第一堆石头

    每个人当前要做出最优策略,因此要比较哪个好,所以用Math.max函数来比较

    如果有三堆石头,piles[0],piles[1],piles[2]

    p1选了第一堆石头:piles[0]-dp[1][2]

    p1选择第三堆石头:piles[2]-dp[0][1]

    pile[0]-dp[1][2]代表着,p1拿取了[0]个石头堆后,减去p2在[1]~[2]相邻石头堆情况下赢得的分数

    最终得到

    dp[i][j]=Math.max(piles[i]-dp[i+1][j],piles[j]-piles[i][j-1])

    ③边界定义

    dp[i][i]=piles[i]

    class Solution {
        public boolean stoneGame(int[] piles) {
            int n=piles.length;
            int [][]dp=new int[n][n];
            //初始化dp[i][i]
            for(int i=0;i<n;i++)
                dp[i][i]=piles[i];
            /**注意这里的两个循环第一个循环dis代表间隔距离,比如说dis=1时,配合接下来i的循环,会不断得到相邻2个石头堆的最优选择策略,比如说{1,2,3,4}时,会得到{1,2}、{2、3}、{3、4}的最优选择策略;当dis=2时,会得到相邻3个石头堆的最优选择策略,得到{1,2,3}、{2、3、4}。**/
            for(int dis=1;dis<n;dis++)
                for(int i=0;i<n-dis;i++)//i仍然表示起始位置
                    dp[i][i+dis]=Math.max(piles[i]-dp[i+1][i+dis],piles[i+dis]-dp[i][i+dis-1]);
            return dp[0][n-1]>0;
        }
    }

     

  • 相关阅读:
    Socket
    利用Python自动生成暴力破解的字典
    【转】六年测试工作的思考1
    【转】手机测试入行三年的感想
    【转】移动测试人员的未来:测试开发技术的融合
    【转】一个互联网项目即将结束的软件测试经验总结
    【转】电子商务网站测试经验总结
    【转】六年软件测试感悟-从博彦到VMware
    使用PL/SQL删除百万条记录的大表
    【转】百万级数据查询优化
  • 原文地址:https://www.cnblogs.com/ak918xp/p/14248406.html
Copyright © 2011-2022 走看看