タイトル説明
指定された配列は、非負の整数の分数を表します。2人のプレーヤーに続いて分画の配列のいずれかの末端からプレイヤーを選択、アレイの両端からの残りの部分をピックアップし、その後、遊技者を取るし続ける....... プレイヤーは一部のみを拾うことができますたびに、画分は、もはや後に拾うことをお勧めしません。望ましいいかなる残りの部分がなくなるまでゲームが終了したとき。最終的に得点の勝利の合計までの選手。
プレイヤーが勝者となりますかどうかを予測するスコアを表す配列を考えます。あなたは、各プレイヤーは自分のスコアを最大化するために再生されると仮定することができます。
输入: [1, 5, 233, 7]
输出: True
解释: 玩家1一开始选择1。然后玩家2必须从5和7中进行选择。无论玩家2选择了哪个,玩家1都可以选择233。
最终,玩家1(234分)比玩家2(12分)获得更多的分数,所以返回 True,表示玩家1可以成为赢家。
問題解決のためのアイデア
パズルパズルは、すべての後に、本当の問題は確かに日和見アルゴリズムがそれを行うことができなくなります。
- 最初のアイデアは、「貪欲」である:常に最大を得るが、これは以下のような仕事、ない
[1, 5, 233, 7]
テストケースを。 - ダイナミックプログラミング:一般的に利用可能であるこの種の問題「二人は最終的に、勝つスマートに十分な、あるとし、」ダイナミックプログラミング解決するためのアルゴリズムを。
dp[i][j]
表現nums[i]
へnums[j]
、両側がスマートに十分であると仮定し、彼らが終了したとき、他のプレイヤー上に上部手とよりは、最大のスコアを取得するためにどのくらいのイエスを。- 以下のために
dp[i][j]
あなたは、上の手を取った場合、nums[i]
は、より上位の手以外のプレイヤーはdp[i+1][j]
、dp[i][j] = nums[i]-dp[i+1][j]
場合は、上部のかかった手を、nums[j]
上側の手よりも、別のプレーヤーdp[i][j-1]
、dp[i][j] = nums[j]-dp[i][j-1]
。要約するとdp[i][j] = Math.max(nums[i]-dp[i+1][j], nums[j]-dp[i][j-1])
アップ:。 - 初期化:とき
i=j
、上側の手を勝つために、特定の、そして他のプレイヤーよりも多くの時間、dp[i][j] = nums[i]
。 - 戻り値:最後のリターンは
dp[0][nums.length-1]
ゼロであることができるよりも大きいです。
参照コード
class Solution {
public:
bool PredictTheWinner(vector<int>& nums) {
int length = nums.size();
if(length <= 1)
return true;
vector<vector<int> > dp(length, vector<int>(length, 0));
for(int i = 0; i < length; i++)
dp[i][i] = nums[i];
for(int i = length-2; i >= 0; i--){ // dp的遍历方向,根据状态转移方程 画画图就能确定
for(int j = i+1; j < length; j++){
dp[i][j] = max(nums[i] - dp[i+1][j], nums[j] - dp[i][j-1]);
}
}
return dp[0][length-1] >= 0;
}
};