UVA 10891 区间DP+博弈思想
很明显带有博弈的味道。让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大。而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j。结合博弈中的思想,表示初始状态i->j情况下,先手能获得的最大分数。后手能获得的就是sum[i][j]-dp[i][j]。接下来枚举先手选取的是两端的哪一段即可。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=105;
int dp[N][N];
int sum[N][N];
int arr[N];
int main(){
int n;
while(scanf("%d",&n),n){
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%d",&arr[i]);
for(int i=n;i>=1;i--){
for(int j=i;j<=n;j++)
if(i==j) sum[i][i]=arr[i];
else sum[i][j]=sum[i][j-1]+arr[j];
}
/* for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cout<<sum[i][j]<<" ";
cout<<endl;
}*/
for(int i=n;i>=1;i--){
for(int j=i;j<=n;j++){
if(i==j) dp[i][j]=sum[i][j];
else{
int m=0;
for(int k=i+1;k<=j;k++)
m=min(dp[k][j],m);
for(int k=j-1;k>=i;k--)
m=min(dp[i][k],m);
dp[i][j]=sum[i][j]-m;
}
}
}
/* for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}*/
printf("%d\n",dp[1][n]-sum[1][n]+dp[1][n]);
}
return 0;
}

浙公网安备 33010602011771号