题目大意:方块消除游戏,给你一个n个方块的序列,相同颜色的一段可以同时消掉,得分为 len^2,问你得分最高时多少?
思路:借用POJ discuss 里的一句话来说,这道题真是优质DP啊。。。 具体解题思路可以看黑书,也可以看这里:http://wenku.baidu.com/view/83d0a76925c52cc58bd6bea8.html,说的很不错。我只是简单的填个坑:设 d[ i ][ j ][ k ] 表示 区域 i 到 区域 j ,区域 j 与后面的 k 个方块相连消掉的最大值,其中 i ~j - 1 只能与自己 i ~ j 中的区域相连。d[ i ][ j ][ k ] = max(d[ i ][ j - 1][ 0 ] + (k+len[ j ])^2, d[ i ][ p ][ k + len[ j ] ] + d[p + 1][ j ][ 0 ] ),其中 col[ p ] == col[ j ] 。
这种题目真心感觉自己想不出来,用一维来表示未来,而且题目虽然A了,但是感觉还是不是很理解,在做几道,回过头来看吧。。。 = =
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 222;
int d[MAXN][MAXN][MAXN];
int col[MAXN],num[MAXN];
int dfs(int i,int j,int k)
{
if(i > j) return 0;
if(d[i][j][k] != -1) return d[i][j][k];
d[i][j][k] = dfs(i,j-1,0) + (k + num[j])*(k + num[j]);
for(int pos = j-1;pos >= i; pos --)
{
if(col[pos] == col[j])
d[i][j][k] = max(d[i][j][k],dfs(i,pos,k + num[j]) + dfs(pos + 1,j-1,0));
}
return d[i][j][k];
}
int main()
{
int _;
scanf("%d",&_);
for(int cas = 1;cas <= _ ;cas ++)
{
int n;
scanf("%d",&n);
int tot = 0;
memset(d,-1,sizeof(d));
for(int i = 1;i<=n;i++)
{
int a;
scanf("%d",&a);
if(tot == 0 || a != col[tot])
{
d[tot][tot][0] = num[tot]*num[tot];
tot++;
col[tot] = a;
num[tot] = 1;
}
else
{
num[tot]++;
}
}
//for(int i = 1;i<=tot;i++)
//printf("col[i] = %d,num[i] = %d\n",col[i],num[i]);
printf("Case %d: %d\n",cas,dfs(1,tot,0));
}
return 0;
}
/*
5
1 1 3 1 1
*/