方法一:动态规划
解题思路
博弈游戏,定义必胜态和必败态。
- 当一个状态能够达到的状态中有必败态,则当前状态为必胜态
- 当一个状态能够达到的所有状态都是必胜态,则当前状态为必败态。
首先设置dp(N)为先手在N的时候的输赢,由于x是任选的(对最终的输赢没有影响),因此可以直接使用x=1来作为每次的选择结果。只要N大于1,那么其输赢总归决定于后者,状态转移为dp(N) = ~dp(N-1)。
class Solution {
public:
bool divisorGame(int N) {
vector<int> temp(N+1,0);
for(int k=1;k<=N;k++)
{
for(int m=1;m<k;m++)
{
if(k%m==0 && temp[k-m]==0)
{
temp[k]=1;
break;
}
}
}
return temp[N];
}
};
方法二:数学规律
推理题: 题目简化成:爱丽丝先手,鲍勃后手,每次减约数,约数不能是自身,谁拿到1谁输。 下面两条定理: A:奇数的约数肯定是奇数。 B:1是所有数的约数,2是所有偶数的约数。
由A推导出C:奇数减任意约数都是偶数。 由B推导出D:偶数减任意约数或奇或偶。
假设每人每步都选择最优方案,则拿到偶数的人可以让对方拿到奇数: 偶->奇->偶->奇->……2->1(输)
所以偶数先手必赢,奇数先手导致后手为偶数(由于C),所以奇数先手必输。
结论:N为奇数时爱丽丝输,返回false。N为偶数时爱丽丝赢,返回true
class Solution {
public:
bool divisorGame(int N)
{
if(N%2==0)
return true;
else
return false;
}
};