题意:
一串数字两个人轮流拿头或尾上的一个数字 求两个人都按最优情况行动最后得分分别是多少
思路:
非常经典的dp一定要会!!
dp[i][j]表示当前拿数字的人在[i,j]区间内能得到的最大得分
状态转移 dp[i][j] = sum[j] - sum[i-1] - min( dp[i+1][j] , dp[i][j-1] )
理解一下就是[i,j]区间的数字除去别人拿的就是我的得分
因为行动方案最优 那么我要找到转移到我现在要求的状态的“敌人最小得分”
通过“敌人最小得分”求出的我的得分一定是我最优的方案
代码:
/*
ID: housera1
PROG: game1
LANG: C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define M 205
int n;
int a[M],sum[M],dp[M][M];
int main(){
int Debug=0;
if(!Debug){
freopen("game1.in","r",stdin);
freopen("game1.out","w",stdout);
}
int i,j,tmp;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
dp[i][i]=a[i];
}
for(i=1;i<n;i++)
{
for(j=1;j+i<=n;j++)
{
dp[j][i+j]=sum[i+j]-sum[j-1]-min(dp[j+1][i+j],dp[j][i+j-1]);
}
}
printf("%d %d\n",dp[1][n],sum[n]-dp[1][n]);
return 0;
}