zoukankan      html  css  js  c++  java
  • [程序员代码面试指南]递归和动态规划-排成一条线的纸牌博弈问题(DP)

    题目

    给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,但是每个玩家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数。

    例子

    arr=[1,2,100,4]。
    开始时玩家A只能拿走1或4。如果玩家A拿走1,则排列变为[2,100,4],接下来玩家B可以拿走2或4,然后继续轮到玩家A。如果开始时玩家A拿走4,则排列变为[1,2,100],接下来玩家B可以拿走1或100,然后继续轮到玩家A。玩家A作为绝顶聪明的人不会先拿4,因为拿了4之后玩家B将拿走100。所以玩家A会先拿1,让排列变为[2,100,4],接下来玩家B不管怎么选,100都会被玩家A拿走。玩家A会获胜,分数为101。所以返回101。
    arr=[1,100,2]。
    开始时玩家A不管拿1还是2,玩家B作为绝顶聪明的人,都会把100拿走。玩家B会获胜,分数为100。所以返回100。

    题解

    • 两个dp数组 offensivePos[i,j]、 defensivePos[i,j] 分别表示对于arr[i,j],当前为先手能够获得的最大得分、当前为后手能够获得的最大的分。
    • 初始化:当i=j ,offensivePos[j][j]=arr[j] , defensivePos[i,j] =0.
    • 其他位置两个数组的转移方程见代码。
    • 遍历顺序是"从上往下从后往左"
    • 时间复杂度O(n^2) ,额外空间复杂度O(n^2).

    代码

    public class Main {
    	public static void main(String args[]) {
    		int[] arr= {1,2,100,4};
    		int winNum=getWinNum(arr);
    		System.out.println(winNum);
    	}
    	
    	public static int getWinNum(int[] arr) {
    		if(arr.length==0) {
    			return 0;
    		}
    		int[][] offensivePos=new int[arr.length][arr.length];
    		int[][] defensivePos=new int[arr.length][arr.length];
    		for(int j=0;j<arr.length;++j) {//由上至下
    			offensivePos[j][j]=arr[j];
    			for(int i=j-1;i>=0;--i) {//由右至左
    				offensivePos[i][j]=Math.max(arr[i]+defensivePos[i+1][j], arr[j]+defensivePos[i][j-1]);//
    				defensivePos[i][j]=Math.min(offensivePos[i+1][j], offensivePos[i][j-1]);
    			}
    		}
    		return Math.max(defensivePos[0][arr.length-1], offensivePos[0][arr.length-1]);
    	}
    }
    
    
  • 相关阅读:
    乔布斯《遗失的访谈》全文:尘封16年的预见
    Java开发超级工具集
    android root权限破解分析
    android linux 命令
    Dom加载让图片加载完再执行
    关于chrome dev tools一些技巧
    1 MySQL基础知识笔记
    教我SQL的老师
    SQL limit和offset的使用
    一次批量复制多个不同结果到剪贴板不用在粘贴文本与被粘贴文本之间反复横跳啦,
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/10952212.html
Copyright © 2011-2022 走看看