UVa 10559 Blocks

区间dp

记 f[l][r][m] 表示方块 l ~ r 右边加上 m 个与方块 r 同色的方块的最大得分, a[i] 表示方块 i 的颜色

记 b[i] 表示 min(j) // j <= i && 方块 j ~ i 的颜色一样 

讨论方块 r 的合并情况得出转移方程:

p = max(b[r], l);

1:直接消去 r ,转移到 f[l][r - 1][0] + (m+r-p+1)*(m+r-p+1)

2:枚举 q < p && a[i] == a[r],转移到 f[q+1][p-1][0] + f[l][q][m+r-p+1]

初始化:f[i][i][0] = 1

答案为:f[1][n][0]

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<fstream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<deque>
 7 #include<vector>
 8 #include<queue>
 9 #include<string>
10 #include<cstring>
11 #include<map>
12 #include<stack>
13 #include<set>
14 using namespace std;
15 typedef long long LL;
16 
17 inline int Read() {
18     int res = 0, f = 1;
19     char ch = getchar();
20     while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
21     while(ch >= '0' && ch <= '9') { res = res*10 + ch - '0'; ch = getchar(); }
22     return res*f;
23 }
24 
25 int T, n, a[205], f[205][205][205], b[205], kase;
26 
27 int dp(int l, int r, int m) {
28     if(f[l][r][m] || r < l) return f[l][r][m];
29     int p = max(b[r], l);
30     int& ans = f[l][r][m];
31     ans = dp(l, p - 1, 0) + (r - p + 1 + m)*(r - p + 1 + m);
32     for(int q = l; q < p; q++)
33         if(a[q] == a[r] && a[q + 1] != a[r]) ans = max(ans, dp(l, q, m + r - p + 1) + dp(q + 1, p - 1, 0));
34     return ans;
35 }
36 
37 int main() {
38     T = Read();
39     while(T--) {
40         n = Read();
41         for(int i = 1; i <= n; i++)
42             a[i] = Read();
43         for(int i = 1; i <= n; i++) {
44             int j = i - 1;
45             while(j && a[j] == a[j + 1]) 
46                 j--;
47             j++;
48             b[i] = j;
49         }
50         memset(f, 0, sizeof(f));
51         for(int i = 1; i <= n; i++)
52             f[i][i][0] = 1;
53         printf("Case %d: %d\n", ++kase, dp(1, n, 0));
54     }
55     return 0;
56 }
View Code

猜你喜欢

转载自www.cnblogs.com/ympc2005/p/12358524.html
今日推荐