Leetcode初学——动态规划算法“除数博弈”(假 )

题目

 

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

 

最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:

 

选出任一 x,满足 0 < x < N 且 N % x == 0 。
用 N - x 替换黑板上的数字 N 。
如果玩家无法执行这些操作,就会输掉游戏。

 

只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 false。假设两个玩家都以最佳状态参与游戏。

 

 

 

示例 1:

 

输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:

 

输入:3
输出:false
题解

这道题真的很有意思,可以说是我目前遇到过的最有意思的题了,虽然它被打上了动态规划的标签,我觉得它其实就是一个脑筋急转弯,题目字面意思很容易理解,找除本身外的因数,找不到就输了。但是它实际做起来其实我觉的是比较的有难度的,通常做动态规划题的思路一般是从小的开始一点点扩大找规律,但是本题不同,本题类似于下棋,每个人其实都有不同的解法,同一个题目不同的解法很有可能就得出不同的结果,打个比方,当N=25时(A为爱丽丝,B为鲍勃):

25 20 16 12 9 6 3 2
5 4 4 3 3 3 1 1
A B A B A B A B

可以看出,最后爱丽丝无路可走失败了,但是换一种走法:

25 20 15 10 5 4 2 1
5 5 5 5 1 2 1 0
A B A B A B A B

同样的题目换种走法爱丽丝又赢了,因为题目说两个人的状态都很好,所以我猜测是有一种必赢的走法,可以让爱丽丝或者鲍勃在不同的情况下获得胜利,但是我实在是没有想出来,就看了下提示:If the current number is even, we can always subtract a 1 to make it odd. If the current number is odd, we must subtract an odd number to make it even.提示出来可以说就很明显了,就是奇偶数的问题,由上面的例子可以看到,只要有人做到2就赢了,2做因数那上一个肯定也是偶数,所以赢得这场游戏的秘诀就是获得偶数的掌控权,当当前数是奇数的时候,奇数的因数要么是1要么肯定也是奇数,而奇数减奇数得到的就是偶数,当当前数是偶数时,偶数只要减一留给对面的肯定是个奇数,最后一定可以得到2这个答案,所以只要题目是奇数,爱丽丝一定赢不了,只要题目是偶数,爱丽丝一定输不了,这就是赢下这场游戏的秘诀,代码很简单,只有一行:

1 class Solution {
2 public:
3     bool divisorGame(int N) {
4         return N%2==0;
5     }
6 };

返回偶数的判定就可以了,动态规划的思路我没有想出来,就看看了大神的题解,确实比较复杂也比较难以理解:

 1 class Solution {
 2 public:
 3     bool divisorGame(int N) {
 4         bool DP[1001];
 5         memset(DP, false, sizeof(DP));
 6         for(int i=1;i<=N;i++){
 7             for(int x=1;x<i;x++){
 8                 if(i%x==0&&!DP[i-x]){
 9                     DP[i]=true;
10                     break;
11                 }
12             }
14         }
15         return DP[N];
16     }
17 };

以上代码出自leetcode:louris,就是循环找当前数的因数然后判断这个数的下一位是赢还是输,赢的话就返回true。

 

posted @ 2020-06-25 18:09  菲特涅米  阅读(170)  评论(0编辑  收藏  举报