Yougth's Game[Ⅲ]
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
有一个长度为n的整数序列,A和B轮流取数,A先取,每次可以从左端或者右端取一个数,所有数都被取完时游戏结束,然后统计每个人取走的所有数字之和作为得分,两人的策略都是使自己的得分尽可能高,并且都足够聪明,求A的得分减去B的得分的结果。
-
输入
- 输入包括多组数据,每组数据第一行为正整数n(1<=n<=1000),第二行为给定的整数序列Ai(-1000<=Ai<=1000)。 输出
- 对于每组数据,输出A和B都采取最优策略的情况下,A的得分减去B的得分的结果。 样例输入
-
3 1 2 3 4 2 4 5 3
样例输出
-
2 0
-
//大神的思路:
-
分析:题意描述的很清楚,就是选择在两端取数,当前取的数不仅能够影响下一次的结果,而且能够影响后面的结果。。。又是一个求最优值,那么是不是可以往dp的方向上想了。区间dp 定义状态dp[ i ] [ j ] 为从 i 到 j 上A的得分,那么B的得分就是sum(i,j)-dp[ i ] [ j ] 转移方程 : dp[i][j]=max(dp[i][j],a[i]+(sum[j]-sum[i]-dp[i+1][j])); 表示区间i--j取第一个 dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1])); 表示区间i--j取最后一个
-
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #define N 1010 #define INF 0x3f3f3f3f using namespace std; int dp[N][N]; int a[N]; int b[N]; int main() { int n,i,j,k; while(scanf("%d",&n)!=EOF) { b[0]=0; for(i=1;i<=n;i++) { scanf("%d",&a[i]); b[i]=b[i-1]+a[i]; } memset(dp,0,sizeof(dp)); for(k=1;k<=n;k++) { for(i=1,j=k;j<=n;i++,j++) { dp[i][j]=-INF; dp[i][j]=max(dp[i][j],a[i]+(b[j]-b[i]-dp[i+1][j])); dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1])); } } printf("%d\n",dp[1][n]-(b[n]-dp[1][n])); } return 0; }