题目
思路
- 想得到亚历克斯的最大值,那么李就要取最小值,考虑使用深度优先搜索遍历,定义函数:f(i,M)f\left ( i,M \right )f(i,M)表示piles从位置i开始到最后的以[1,2*M]为范围所能取到的最大值,使用公式
f(i,M)=sum(piles[i:])−min(f(i+x,max(m,i))),1≤x≤2∗Mf\left ( i,M \right )=sum\left ( piles\left [ i: \right ] \right )-min\left ( f\left ( i+x,max(m,i) \right )\right ),1\leq x\leq2*M f(i,M)=sum(piles[i:])−min(f(i+x,max(m,i))),1≤x≤2∗M
- 前者表示亚历克斯所能取到的最大值(当然实际不能取到,这表示从数组i开始后面所有的和),后者表示亚历克斯取完了以后,李能取到的最小值,两者相减为亚历克斯实际能取到的最大值。
- 同时,为了节省计算,使用dp二维数组来存储 f(i,M) 的结果,行表示i,列表示M,如果有了相应的结果就使用相应的结果,如果没有则递归,并存入数组。
时间
代码
class Solution {
private int n=0;
private int[][] dp;
public int stoneGameII(int[] piles) {
n=piles.length;
int[] s=new int[n];
s[n-1]=piles[n-1];
for(int i=n-2;i>=0;i--){
s[i]=s[i+1]+piles[i];
}
dp=new int[2*n][2*n];
return dfs(0,1,s);
}
public int dfs(int index,int M,int[] s){
if(index>n){
return 0;
}else if(index+2*M>=n){
return s[index];
}else{
int min=Integer.MAX_VALUE;
for(int i=1;i<=2*M;i++){
if(dp[index+i][Math.max(M,i)]!=0){
min=Math.min(min,dp[index+i][Math.max(M,i)]);
}else{
int temp=dfs(index+i,Math.max(M,i),s);
min=Math.min(min,temp);
dp[index+i][Math.max(M,i)]=temp;
}
}
return s[index]-min;
}
}
}