#include <iostream>
#include <vector>
using namespace std;
bool canWin(int n)
{
vector<bool>dp(max(n+1,4));
dp[3] = dp[1] = dp[2] = true;
for(int i = 4; i <= n; ++i)
{
dp[i] = !dp[i-1] || !dp[i-2] || !dp[i-3];
}
return dp[n];
}
int dfs(const vector<int>& piles, int i, int j, vector<vector<int>>&memo)
{
if(i > j) return 0;
if(memo[i][j] != -1) return memo[i][j];
memo[i][j] = max(piles[i] - dfs(piles,i+1,j,memo),piles[j]-dfs(piles,i,j-1,memo));
return memo[i][j];
}
bool predictWinner(const vector<int>& piles)
{
int n = piles.size();
vector<vector<int>>memo(n,vector<int>(n,-1));
return dfs(piles,0,n,memo) > 0;
}
bool dfs(int n, vector<int>&memo)
{
if(1 == n)return false;
if(memo[n]!=-1)return memo[n];
bool canWin = false;
for(int i = 1; i <= n/2; ++i)
{
if(n % i == 0 && !dfs(n-i,memo))
{
canWin = true;
break;
}
}
return memo[n] = canWin;
}
bool divisorGame(int n)
{
vector<int>memo(n+1,-1);
return dfs(n,memo);
}
bool stonesGame(const vector<int>& stones)
{
int n = stones.size();
vector<vector<int>>memo(n,vector<int>(n,-1));
int max = dfs(stones,0,n-1,memo);
return memo[0][n-1] > 0;
}
int minmax(const vector<int>& nums, int index, vector<int>&memo)
{
if(index == nums.size())return 0;
if(memo[index]!=-1)return memo[index];
int res = INT_MIN;
int score = 0;
for(int i = index; i < index + 3 && i < nums.size(); ++i)
{
score += nums[i];
res = max(res,score - minmax(nums,index + 1,memo));
}
return memo[index] = res;
}
int stoneGameIII(const vector<int>& nums)
{
int n = nums.size();
vector<int>memo(n,-1);
return minmax(nums,0,memo);
}
bool winSquareGame(int n)
{
vector<bool>dp(n+1,false);
for(int i = 1; i <= n; ++i)
{
for(int k = 1; k * k <= i; ++k)
{
if(!dp[i-k*k])
{
dp[i] = true;
break;
}
}
}
return dp[n];
}
int main()
{
//LeetCode292
cout << canWin(4) << endl;
//LeetCode486
vector<int>v{1,5,233,7};
cout << predictWinner(v) << endl;
//LeetCode1025
cout << divisorGame(4) << endl;
//LeetCode877
vector<int>stones{5,3,4,5};
cout << stonesGame(stones) << endl;
//LeetCode1406
vector<int>nums{1,2,3,-9};
cout << stoneGameIII(nums) << endl;
//LeetCode1510
int n = 1;
cout << winSquareGame(n) << endl;
return 0;
}