タイトル内容
ゲーム内のいくつかの石とアリスとボブヒープ。行の石の杭は、石がスコアつのスタックに対応するそれぞれは、アレイstoneValueによって与えられます。
アリスとボブはターンの石を取り、アリスは常に最初に起動します。各プレイヤーのターンでは、プレイヤーは、石のヒープ1、2または3の前に石の休息を取ることができます。すべての石が離れて撮影されているまでゲームは続きます。
各杭に対応する各プレイヤーのための最終的なスコアは、彼が石とスコアを得ました。各プレイヤーの初期スコアが0です。ゲームの目的は、ゲームでも引き分けであってもよいし、最高得点のプレイヤーがゲームに勝つ、最高点で決定されます。
アリスとボブが最善の戦略をとっていると仮定します。アリスは「アリス」への復帰に勝てば、ボブは(同じスコア)「タイ」のリターンを描き、リターン「ボブ」に勝ちました。
出典:滞在ボタン(LeetCode)
リンク:https://leetcode-cn.com/problems/stone-game-iii
トピック分析
この質問は今実際にはアレイとの数の両端取る、我々はまだ似て使用することができますので、自分の最適なソリューションを選択するために、両方の当事者があり、非常に類似した動的なプログラミングを問題を解決します。
問題解決のためのアイデア
我々は前方から後方に分析した場合、両側は、最適なので、両側の各戦略は、ポリシーを選択した後に、最適なソリューションの他の側面を知ることは困難である3つのオプションがあり、それを解析することは困難です。私たちは石の順番に従って分析から前方に移動する必要があるので、最適な状態の導入の始まりを注ぎます。
状態は示していますから成る最後の小石の石に、i番目の注文シーケンスDP [i]の代表、現在のプレイヤーが石を取り得られる最大は。
それが最後の石を獲得するために、私から固定されているので、それはすべての石のスコアであると、2人の選手と石の合計スコアの得点ながら、現在の最高得点を取るためにそう砂利石を取ると同等です反対側の最低得点後。現在のテイク石我々は、エミュレートこれら三つを知っていれば、最適なソリューションの他の側面ので、借入の1,2,3三種類は、我々は最小限に借りての最適なソリューション他の種類を選択し、後に取りました。次のように状態遷移方程式はあります:
// sum[i]为第i个石子到最后一个石子的总得分
dp[i] = sum[i] - min(dp[i+1], dp[i+2], dp[i+3]);
状態遷移式で、その後、境界条件ができることに注意してください。
ACコード
class Solution {
public:
string stoneGameIII(vector<int>& stoneValue) {
int n = stoneValue.size();
int dp[n];
// res[i] 表示从第i个石子到最后一个石子的得分之和
int res[n];
res[n-1] = stoneValue[n-1];
for(int i=n-2;i>=0;--i){
res[i] = res[i+1]+stoneValue[i];
}
//dp[n-1] = res[n-1];
for(int i=n-1;i>=0;--i){
int minv;
// 这里表示如果剩下的石子小于等于3
// 该选手可以一次把所有石子取完
// minv = 0就表示另一个选手没有石子可以取
if(i+3>=n) minv = 0;
else minv = INT_MAX;
if(i+1<n){
minv = min(minv, dp[i+1]);
}
if(i+2<n){
minv = min(minv, dp[i+2]);
}
if(i+3<n){
minv = min(minv, dp[i+3]);
}
dp[i] = res[i]-minv;
}
if(res[0]-dp[0]>dp[0]) return "Bob";
else if(res[0]-dp[0] == dp[0]) return "Tie";
else return "Alice";
}
};