UVA10059 Blocks 题解报告

题目传送门

【题目大意】

有$n$个方块,每个方块有一个颜色。现在要消除这些方块,一段颜色相同的$k$个方块消除后的得分为$k^2$,求消除所有方块后的最大得分。

【思路分析】

这题还是很容易想到DP的?

设$f[i][j][k]$表示当前处理到$[i,j]$,右边还有$k$个和$j$颜色相同的方块,我们考虑分情况转移:

1.把$j$和后面$k$个同色方块一起消掉,$s[j]$表示$j$右边和$j$颜色相同的方块总数

$$f[i][j][k]=max\{f[i][j-1][0]+(k+1)^2\}(k\in[0,s[j]])$$

2.在$[i,j]$之间找一个和$j$颜色相同的方块$p$,把$[p+1,j-1]$之间的方块消掉,然后把$p$和$j$以及$j$后面的$k$个颜色相同的方块一起消掉,$c[j]$代表$j$的颜色

$$f[i][j][k]=max\{f[i][p][k+1]+f[p+1][j-1][0]\}(k\in[0,s[j]],p\in[i,j-1]\&\&c[p]=c[j])$$

然后就是要注意一下循环的顺序,一定是从后往前转移!!!因为如果从前往后转移即$i,j$从小到大枚举,那么在求$f[i][j][k]$的时候还没有求出$f[p+1][j-1][0]$的值,这样是错的!

最后的答案是$f[1][n][0]$

【代码实现】

UVA10059 Blocks 题解报告
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define g() getchar()
 8 #define rg register
 9 #define go(i,a,b) for(rg int i=a;i<=b;i++)
10 #define back(i,a,b) for(rg int i=a;i>=b;i--)
11 #define db double
12 #define ll long long
13 #define il inline
14 #define pf printf
15 #define mem(a,b) memset(a,b,sizeof(a))
16 using namespace std;
17 int fr(){
18     int w=0,q=1;
19     char ch=g();
20     while(ch<'0'||ch>'9'){
21         if(ch=='-') q=-1;
22         ch=g();
23     }
24     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
25     return w*q;
26 }
27 const int N=202;
28 int T,n,c[N],s[N],f[N][N][N];
29 int main(){
30     //freopen("","r",stdin);
31     //freopen("","w",stdout);
32     T=fr();
33     go(t,1,T){
34         n=fr();
35         mem(f,0);mem(s,0);
36         go(i,1,n) c[i]=fr();
37         back(i,n-1,1) go(j,i+1,n) if(c[i]==c[j]) s[i]++;
38         back(i,n,1) go(j,i,n){//i要从大到小枚举!
39             go(p,i,j-1)
40                 if(c[p]==c[j])
41                     go(k,0,s[j]) f[i][j][k]=max(f[i][j][k],f[i][p][k+1]+f[p+1][j-1][0]);
42             go(k,0,s[j]) f[i][j][k]=max(f[i][j][k],f[i][j-1][0]+(k+1)*(k+1));
43         }
44         pf("Case %d: %d\n",t,f[1][n][0]);
45     }
46     return 0;
47 }
代码戳这里
上一篇:内存泄漏检查工具valgrind使用方法


下一篇:Oracle的表压缩