ゲーム内のいくつかの石を持つアレックスとリー・ヒープ。行スタックの偶数石、各スタックは、正の整数石片杭[I]を有します。誰が勝者を決定するための最も石でゲームを持っています。石の合計数には引き分けがない、奇妙です。アレックスとリーはターンを取る、アレックスが最初に開始します。各ターンでは、プレイヤーは、行の先頭や末尾から石の全体の杭を奪います。この状況は、石の勝利の手のほとんどを、その時点でこれ以上の石の山、まで続きました。アレックスがゲームに勝つときアレックス・リーの前提と最高レベルのプレーには、trueを返す、リーは試合に勝つためにはfalseを返します。
例:
入力:[5,3,4,5]
出力:真
説明:のみ5または5の後に石を取る前に、アレックスはまず、スタート。彼は5の前に取ったと仮定し、この行は[3,4,5]となります。リーは3を取った前に、そして残りは[4,5]であれば、アレックスは10分後に5勝を取りました。リーは離れて、その後、残りは[3,4]である場合には、図5に示すように、アレックスは9分後に4勝を取りました。これは、我々がtrueを返すように、かつてのテイク5石アレックスは、動きの勝利であることを示唆しています。
リンク:https://leetcode-cn.com/problems/stone-game
[思考]
1.dp問題。まず第一に、すべての時間は2つの借入がある、または石の山の前にほとんどを選択するか、石の最後の山を取ります。オブジェクトは、二つの三次元配列を有し、ここで関与しているので、それぞれの状態を表すのに必要なIからJ番号石のヒープに積ま石、DP [I]と番号付けされている[J] [0] [誰取得、DPを示し[1] i]の[jの後]で取得します。
2.最適なケースを確保するために必要以上の各テイクの後、左、右、石の最後の山を取って表し、石の山を取る前に、ほとんどを表します。どちらの場合も大きな値を選択してください。存在状態方程式:DP [I] [J] [0] = MAX(パイル[I] + DP [I + 1] [j] [1]、杭[J] + DP [I]、[J-1] [1]);ここで、左=杭[I] + DP [I + 1] [j] [1]、右=杭[J] + DP [I]、[J-1] [1]。
上記の状態方程式では、ヒープの石から石のスタックを考慮jに私の番号を付け、選択した例最適値を取得する人は、これに基づいて最適値テイクによって選択されます。そのため、
- DPによって人物が正面を取得石の山を取った場合、テイクバック[I] [J] [1]〜[I + 1、j]の最適値を選択して、人が優先しなければならない後に、この時間に、すなわち、 DP [I + 1] [J] [0]。
- 人は最後の取得に石の山、最適な値を選択するには、[I、J + 1]に[J] [1] [i]はDPの後にそれを取る人たち、そして人は優先権を取るために持っていた後、この時間がかかった場合、すなわち、 DP [I] [J-1] [0]。
より勝つ方にそれを取ったかを知るための大きな石の価値の最終判断DP [0] [pilesSize-1] [0]とDP [0] [pilesSize-1] [1]。
[J] [0] = MAX(パイル[I] + DP [I + 1] [j] [1] [i]は、このアレイはプログレッシブDPによるDP時に割り当てられていないことに留意すべきです、杭[J] + DP [I]、[J-1] [1])、次に割り当てI、知るJ、I、J必要とI、J-1 + 1の値、。簡単な図面は対角線割り当てに従って、知っているかもしれません。再帰的には、全体のコードを次の。
bool stoneGame(int* piles, int pilesSize){
int i,j,l;
int dp[pilesSize][pilesSize][2];
int left,right;
for(i=0;i<pilesSize;i++){
dp[i][i][0]=piles[i];
dp[i][i][1]=0;
}
for(l=1;l<pilesSize;l++){
for(i=0;i<pilesSize-l;i++){
j=i+l;
left=piles[i]+dp[i+1][j][1];
right=piles[j]+dp[i][j-1][1];
if(left>right){//选择值大的一种情况,对于特定的i,j需要更新以下两个变量
dp[i][j][0]=left;
dp[i][j][1]=dp[i+1][j][0];
}
else{
dp[i][j][0]=right;
dp[i][j][1]=dp[i][j-1][0];
}
}
}
if(dp[0][pilesSize-1][0]>dp[0][pilesSize-1][1])//如果先选的人最终值大于后选者,返回true
return true;
else
return false;
}