ACM之預測贏家

題目以下java

圖片.png


    零和博弈問題:表示全部博弈方的利益之和爲零或者是一個常數,即一方有得其餘方必有失,且在博弈中各方是不會合做的。解決此類問題的方法有極小化極大算法等,那就先來學習一下這個極小化極大算法:Minimax算法,是一種找出失敗的最大可能性中的最小值的算法。node

算法僞代碼(維基百科)算法

function minimax(node, depth)
    if node is a terminal node or depth = 0
        return the heuristic value of node
    if the adversary is to play at node
        let α := +∞
        foreach child of node
            α := min(α, minimax(child, depth-1))
    else {we are to play at node}
        let α := -∞
        foreach child of node
            α := max(α, minimax(child, depth-1))
    return α

    從僞代碼中能夠看到:在對手回合時,算法默認對手的收益爲無窮大;在本身回合時收益爲無窮小。在迭代過程當中,須要進行玩家判斷,由於遊戲的目的就是最小化對手的優點而最大化本身的利益,因此在對手的回合時,對手須要讓我最小化利益min,而在本身的回合時,我確定是最大化本身的利益,因此用max。那麼Max和Min分別都是怎麼計算出利益大小的呢?遞歸!不知道利益大小就遞歸地往下問,問到最後再遞歸地回答上來,利益就計算出來了數組

    那針對這道題的解答思路就有了:ide

    咱們用一個solve(nums)函數來計算當前玩家從nums中能夠得到的最大收益,當收益>=0時,玩家1獲勝。函數

solve(nums) = max(nums[0] - solve(nums[1:]), nums[-1] - solve(nums[:-1]))學習

爲何是nums[0]-solve(nums[1:])而不是+呢?由於玩家拿完一個數以後就輪到別人了,此時solve函數是別人的收益,咱們用累計本身收益,並扣除對手收益的方式來表示本身的收益最後是否比對手多,若是結果大於0就表示比對手多。spa

(備註:nums[-1],nums[:-1]的意思:Python的索引方式,帶冒號的叫作數組的「切片」,冒號前的數是起點的索引,後面的是終點索引。若是沒有起點默認是0,若是沒有終點默認就是到最後。舉個栗子:   nums[1,2,3,4,5],則 nums[-1] = 5 , nums[ :-1] = [1,2,3,4] , nums[ 1:] = [2,3,4,5] )code

Java實現遞歸

public class PredictTheWinnerBter {
     public static boolean solution(int[] nums){
          return helper(nums,0,nums.length - 1) >= 0;
     }
     private static int helper(int[] nums,int s,int e) {
          return s == e ? nums[e] : Math.max(nums[s] - helper(nums,s+1,e), nums[e] - helper(nums,s,e-1));
     }
      public static void main(String[] args){
           int[] nums = new int[]{1,5,255,2};
           System.out.println(solution(nums));
      }
}

    這道題剛開始真的不會寫,但這種題目能夠說是很是經典了。還有解法是自上而下的DP(動態規劃),找時間研究一下。


參考:Leetcode解題報告

相關文章
相關標籤/搜索