今天开始刷HackerRank。部分题解记录下。
题目:Play Game
链接:https://www.hackerrank.com/challenges/play-game
代码:
<pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n;
long long num[100100];
long long sum[100100];
long long dp[100100];
int main(){
cin>>t;
while(t--){
memset(sum,0,sizeof(sum));
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
cin>>n;
for(int i=0;i<n;i++){
cin>>num[i];
}
for(int i=n-1;i>=0;i--){
sum[i]=sum[i+1]+num[i];
}
dp[n-1]=sum[n-1];
dp[n-2]=sum[n-2];
dp[n-3]=sum[n-3];
for(int i=n-4;i>=0;i--){
dp[i] = sum[i]-min(min(dp[i+1],dp[i+2]),dp[i+3]);
}
cout<<dp[0]<<endl;
}
}
思路:
1. 游戏的过程是从前向后的,即依次从i=0取到i=n-1。
2. dp的过程是从后向前的,即dp[i]表示先手A从i开始取,两人取完所有砖块后,先手A能取得的最大分数。
3. 值得注意的,这里的dp[i]表示从i开始取,使用最优策略能取得的最大分数。不区分先手A还是后手B。无论AB都会按照这个策略。原因是 有从i开始取到n-1的限制。
4. dp[i]的状态和dp[i+1],dp[i+2],dp[i+3]有关。从i开始取有3个选择,取1、2、3个。当这个人X取完j个后(j=1,2,3),下个人Y会在i+j位置开始,使用最优策略。下个人Y的之后的得分是dp[i+j]。这个人X的之后得分是Sum(i+j,n-1)-dp[i+j]。这个人X的在i位置的得分是dp[i]=Num(i,i+j)+Sum(i+j,n-1)-dp[i+j]=Sum(i,n-1)-dp[i+j]。选择j=1,2,3中的一个,使得dp[i]取最大值。</span><span style="font-family: SimSun;">最后dp[0]即为所求。