poj 1390 Blocks 区间DP

Description:

给你一堆方块,颜色相同可以消去,每次消去的价值为消去方块的个数的平方。单个方块可以消去。问你最后收获的最大价值为多少

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 const int N = 220;
 6 int dp[N][N][N], g[N][N], col[N]; 
 7 //dp[i][j][k]表示i-j这一段消得只剩k个且k个块都相同时收获的最大价值,g[i][j]表示i-j能收获的最大价值
 8 int n, m;
 9 int main(){
10     int T, kase = 0;
11     scanf("%d", &T);
12     while(T--){
13         scanf("%d", &n);
14         for(int i = 1; i <= n; i++) scanf("%d", &col[i]);
15         memset(dp, -63, sizeof(dp)); //达不到的状态为负无穷大
16         memset(g, 0, sizeof(g));
17         for(int i = 1; i <= n; i++)
18           dp[i][i][1] = 0, dp[i][i][0] = 0, g[i][i] = 1;
19         for(int l = 2; l <= n; l++)
20           for(int i = 1, j; i + l - 1 <= n; i++){   //枚举区间
21               j = i + l - 1;
22               if(col[i] == col[j]){  //如果区间首尾相同 说明可能通过消去区间内的方块更新dp数组
23                   for(int k = 1; k <= l; k++){  //枚举可能的相同剩余方块数
24                       for(int t = i; t < j; t++)  //枚举区间的每个方块
25                         if(col[i] == col[t])   //如果发现有方块与区间首方块相同
26                             //那么i到t的方块可以消掉t+1-j的方块后 达到dp[i][t][k-1]的状态
27                             //把两边的两边产生的价值累加之后更新dp数组
28                           dp[i][j][k] = max(dp[i][j][k], dp[i][t][k - 1] + g[t + 1][j - 1]);
29                       //那么区间g[i][j]的价值可以表现为状态dp[i][j][k]的价值和消掉剩下的k个方块的价值
30                       g[i][j] = max(g[i][j], dp[i][j][k] + k * k);  
31                   }
32               }
33               for(int k = i; k < j; k++)  //重新刷一波更新g数组
34                 g[i][j] = max(g[i][j], g[i][k] + g[k + 1][j]);
35           }
36         printf("Case %d: %d\n", ++kase, g[1][n]);
37     }
38     return 0;
39 }
View Code

猜你喜欢

转载自www.cnblogs.com/Rorshach/p/9275825.html
今日推荐