动态规划一-博弈类

292. Nim Game

You are playing the following Nim Game with your friend:

  • Initially, there is a heap of stones on the table.
  • You and your friend will alternate taking turns, and you go first.
  • On each turn, the person whose turn it is will remove 1 to 3 stones from the heap.
  • The one who removes the last stone is the winner.

Given n, the number of stones in the heap, return true if you can win the game assuming both you and your friend play optimally, otherwise return false

Example 1:

Input: n = 4
Output: false
Explanation: These are the possible outcomes:
1. You remove 1 stone. Your friend removes 3 stones, including the last stone. Your friend wins.
2. You remove 2 stones. Your friend removes 2 stones, including the last stone. Your friend wins.
3. You remove 3 stones. Your friend removes the last stone. Your friend wins.
In all outcomes, your friend wins.

Example 2:

Input: n = 1
Output: true

Example 3:

Input: n = 2
Output: true

Constraints:

  • 1 <= n <= 231 - 1
class Solution {
    public boolean canWinNim(int n) {
        Boolean[] status = new Boolean[n+1];
        return helper(n,status);
    }
    private boolean helper(int n,Boolean[] status){
        if(n<=0) return false;//如果没有剩余的石头了,那么我就输了
        if(status[n]!=null) return status[n];
        for(int i=1;i<4;i++){//我可以取1,2,3个石头
            if(!helper(n-i,status)) return true; //如果我拿i个,剩下的如果对手能赢(true),那我就输了,对手输了(false) 我就能赢
        }
        return status[n]=false;
    }
}

 

486. Predict the Winner

Medium

You are given an integer array nums. Two players are playing a game with this array: player 1 and player 2.

Player 1 and player 2 take turns, with player 1 starting first. Both players start the game with a score of 0. At each turn, the player takes one of the numbers from either end of the array (i.e., nums[0] or nums[nums.length - 1]) which reduces the size of the array by 1. The player adds the chosen number to their score. The game ends when there are no more elements in the array.

Return true if Player 1 can win the game. If the scores of both players are equal, then player 1 is still the winner, and you should also return true. You may assume that both players are playing optimally.

Example 1:

Input: nums = [1,5,2]
Output: false
Explanation: Initially, player 1 can choose between 1 and 2. 
If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2). 
So, final score of player 1 is 1 + 2 = 3, and player 2 is 5. 
Hence, player 1 will never be the winner and you need to return false.

Example 2:

Input: nums = [1,5,233,7]
Output: true
Explanation: Player 1 first chooses 1. Then player 2 has to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233.
Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win. 

Constraints:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 107

 

 

暴力dfs

class Solution {
    public boolean PredictTheWinner(int[] nums) {
        return getScore(nums,0,nums.length-1,1)>=0;
    }
    private int getScore(int[] nums,int l,int r,int turn){
        if(l==r) return nums[l]*turn;
        int a = nums[l]*turn + getScore(nums,l+1,r,-turn);
        int b = nums[r]*turn + getScore(nums,l,r-1,-turn);
        return turn*Math.max(turn*a,turn*b);
    }
}

增加memoization

class Solution {
    public boolean PredictTheWinner(int[] nums) {
        int len = nums.length;
        Integer[][] mem = new Integer[len][len];
        return getScore(nums,0,nums.length-1,1,mem)>=0;
    }
    private int getScore(int[] nums,int l,int r,int turn,Integer[][] mem){
        if(mem[l][r]!=null) return mem[l][r];
        if(l==r) {
            mem[l][r]= nums[l]*turn;
            return mem[l][r];
        }
        int a = nums[l]*turn + getScore(nums,l+1,r,-turn,mem);
        int b = nums[r]*turn + getScore(nums,l,r-1,-turn,mem);
        mem[l][r] = turn*Math.max(turn*a,turn*b);
        return mem[l][r];
    }
}
1025. Divisor Game
Easy

Alice and Bob take turns playing a game, with Alice starting first.

Initially, there is a number n on the chalkboard. On each player's turn, that player makes a move consisting of:

  • Choosing any x with 0 < x < n and n % x == 0.
  • Replacing the number n on the chalkboard with n - x.

Also, if a player cannot make a move, they lose the game.

Return true if and only if Alice wins the game, assuming both players play optimally.

Example 1:

Input: n = 2
Output: true
Explanation: Alice chooses 1, and Bob has no more moves.

Example 2:

Input: n = 3
Output: false
Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves. 

Constraints:

  • 1 <= n <= 1000
class Solution {
    public boolean divisorGame(int n) {
        return check(n);
    }
    private boolean check( int n ){
        if(n==1) return false;//如果当前为1,那就输了
        for(int i=1;i<n;i++){
            if(n%i==0){
                if(!check(n-i)) return true;//如果对方输了,我就赢了
            }
        }
        return false;
    }
}

增加memoization

class Solution {
    public boolean divisorGame(int n) {
        Boolean[] mem = new Boolean[n+1];
        return check(n,mem);
    }
    private boolean check( int n , Boolean[] mem){
        if(n==1) return false;
        if(mem[n]!=null) return mem[n];
        for(int i=1;i<n;i++){
            if(n%i==0){
                if(!check(n-i,mem)) return true;
            }
        }
        mem[n]=false;
        return false;
    }
}

 

486. Predict the Winner
Medium

You are given an integer array nums. Two players are playing a game with this array: player 1 and player 2.

Player 1 and player 2 take turns, with player 1 starting first. Both players start the game with a score of 0. At each turn, the player takes one of the numbers from either end of the array (i.e., nums[0] or nums[nums.length - 1]) which reduces the size of the array by 1. The player adds the chosen number to their score. The game ends when there are no more elements in the array.

Return true if Player 1 can win the game. If the scores of both players are equal, then player 1 is still the winner, and you should also return true. You may assume that both players are playing optimally.

 Example 1:

Input: nums = [1,5,2]
Output: false
Explanation: Initially, player 1 can choose between 1 and 2. 
If he chooses 2 (or 1), then player 2 can choose from 1 (or 2) and 5. If player 2 chooses 5, then player 1 will be left with 1 (or 2). 
So, final score of player 1 is 1 + 2 = 3, and player 2 is 5. 
Hence, player 1 will never be the winner and you need to return false.

Example 2:

Input: nums = [1,5,233,7]
Output: true
Explanation: Player 1 first chooses 1. Then player 2 has to choose between 5 and 7. No matter which number player 2 choose, player 1 can choose 233.
Finally, player 1 has more score (234) than player 2 (12), so you need to return True representing player1 can win.

 Constraints:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 107
class Solution {
    public boolean PredictTheWinner(int[] nums) {
        return helper(nums, 0, nums.length - 1) >= 0;
    }
    private int helper(int[] nums, int left, int right) {
        if(left == right) return nums[left];
//如果我选left,我能赢对方多少
int leftR = nums[left] - helper(nums, left + 1, right);
     //如果我选right,我能赢对方多少
int rightR = nums[right] - helper(nums, left, right - 1); return Math.max(leftR, rightR); } }

 

加mem避免重复计算

class Solution {
    public boolean PredictTheWinner(int[] nums) {
        return helper(nums, 0, nums.length - 1, new Integer[nums.length][nums.length]) >= 0;
    }
    private int helper(int[] nums, int left, int right, Integer[][] mem) {
        if(left == right) return nums[left];
        if(mem[left][right] != null) return mem[left][right];
        int leftR = nums[left] - helper(nums, left + 1, right, mem);
        int rightR = nums[right] - helper(nums, left, right - 1, mem);
        mem[left][right] = Math.max(leftR, rightR);
        return mem[left][right];
    }
}

 

posted @ 2021-12-10 10:52  xiaoyongyong  阅读(98)  评论(0)    收藏  举报