JAVA算法:取石子游戏(博弈)

JAVA算法:取石子游戏(博弈)

题目大意是:Alex和Lee用一堆石头玩游戏,偶数堆石头排成了一行。每一堆石头都是由正整数表示的石头组成,记为piles[i]。游戏最终以谁手中取走的石头最多来决出胜负。由于石头的总数是奇数,所以没有平局产生。

Alex和Lee轮流进行取石头,Alex先开始。 每回合,玩家从行的开始或结束处取走整堆石头。 这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。

假设Alex和Lee都表现的很出色,当Alex赢得比赛时返回 true

举例 1:

输入: [5,3,4,5]
输出: true
解释: 

Alex先开始取石头,他可以从最左边取5,或者最右边取5;

假设他选择从左边取石头,这样剩下的就是 [3,4,5]

如果LEE取了3,则剩下[4,5],这时Alex再从右边取5,则他累计有10块石头。而LEE最多有7块石头。

如果LEE取了右边的5,则剩下[3,4],这时Alex从右边取4,则他累计有9块石头。而LEE最多有8块石头。

这样的选择方式,Alex获胜,从而我们的算法返回 true。

注意限制条件:

2 <= piles.length <= 500
piles.length 是偶数.
1 <= piles[i] <= 500
sum(piles) 是奇数.


算法设计

package com.bean.algorithmbasic;

import java.util.Arrays;

public class StoneGame {

	/*
	 * pickStones
	 */
	public static boolean pickStones2DP(int[] p) {
		int n = p.length;
		int[][] dp = new int[n][n];
		for (int i = 0; i < n; i++) {
			dp[i][i] = p[i];
		}
		for (int d = 1; d < n; d++) {
			for (int i = 0; i < n - d; i++) {
				dp[i][i + d] = Math.max(p[i] - dp[i + 1][i + d], p[i + d] - dp[i][i + d - 1]);
			}

		}
		return dp[0][n - 1] > 0;
	}
	
		
	public static boolean stoneGame1DP(int[] p) {
        int[] dp = Arrays.copyOf(p, p.length);;
        for (int d = 1; d < p.length; d++)
            for (int i = 0; i < p.length - d; i++)
                dp[i] = Math.max(p[i] - dp[i + 1], p[i + d] - dp[i]);
        return dp[0] > 0;
    }
	
	
	public static boolean stoneGame(int[] piles) {
		// If pile length is even, Alex can choose either the odd or even pile to pick
	        if (piles == null || piles.length == 0 || (piles.length & 1) == 0) {
	            return true;
	        }
	        int n = piles.length;
	        // dp[i][j] represents the first taker of piles i to j can win the second taker dp[i][j] score
	        int[][] dp = new int[n][n];
	        for (int i = n; i >= 0; i--) {
	            for (int j = i; j < n; j++) {
	                if (i == j) {
	                    dp[i][j] = piles[j];
	                } else {
	                    dp[i][j] = Math.max(piles[j] - dp[i][j - 1], piles[i] - dp[i + 1][j]);
	                }
	            }
	        }
	        return dp[0][n - 1] > 0;
	    }
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//int[] nums = new int[] { 5, 3, 4, 5 };
		//注意下面的测试数据中,Alex如果从左边取3,则失败;如果从右边取3,则获胜。
		//题目说了,他们都发挥的很好,意味着Alex从右边取石头。
		int[] nums = new int[] { 3,7,2,3 };
		boolean flag_2DP = pickStones2DP(nums);
		boolean flag_1DP = stoneGame1DP(nums);
		boolean flag_stonegame =stoneGame(nums);
		System.out.println("flag_2DP is: " + flag_2DP);
		System.out.println("flag_1DP is: " + flag_1DP);
		System.out.println("flag_stonegame is: " + flag_stonegame);
	}

}

程序运行结果:

flag_2DP is: true
flag_1DP is: true
flag_stonegame is: true

你可能感兴趣的:(算法分析与设计,算法分析与设计,JAVA算法设计,取石子游戏算法,取石头算法)