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; }