LightOJ1031 Easy Game(区间DP)

我可能真想不到这题是区间DP,不过知道是区间DP想了下就AC了。

dp[i][j]表示局面为ai...aj先手能获得与后手得分的最大差值

那么转移到当前状态就是枚举中间的位置,分成两边,其中一边先手全部取另一边就是新的局面,后手变成新的先手的局面,而后手也会采取最优策略也会尽量让剩下这个局面差值最大。方程如下:

dp[i][j] = max( sum[i][j] , sum[i][k]-dp[k+1][j] , sum[k+1][j]-dp[i][k] ) (i<=k<j)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define INF (1<<29)
 6 int d[111][111];
 7 int main(){
 8     int t,n,s[111]={0};
 9     scanf("%d",&t);
10     for(int cse=1; cse<=t; ++cse){
11         scanf("%d",&n);
12         for(int i=1; i<=n; ++i) scanf("%d",s+i),s[i]+=s[i-1];
13         for(int i=1; i<=n; ++i){
14             for(int j=1; j<=n; ++j) d[i][j]=-INF;
15             d[i][i]=s[i]-s[i-1];
16         }
17         for(int len=1; len<n; ++len){
18             for(int i=1; i+len<=n; ++i){
19                 d[i][i+len]=s[i+len]-s[i-1];
20                 for(int j=i; j<i+len; ++j) d[i][i+len]=max(d[i][i+len],s[j]-s[i-1]-d[j+1][i+len]);
21                 for(int j=i+len; j>i; --j) d[i][i+len]=max(d[i][i+len],s[i+len]-s[j-1]-d[i][j-1]);
22             }
23         }
24         printf("Case %d: %d
",cse,d[1][n]);
25     }
26     return 0;
27 }
原文地址:https://www.cnblogs.com/WABoss/p/5125222.html