题解:方块消除
题目
题目描述
Jimmy最近迷上了一款叫做方块消除的游戏。游戏规则如下:n个带颜色方格排成一列,相同颜色的方块连成一个区域(如果两个相邻方块颜色相同,则这两个方块属于同一区域)。为简化题目,将连起来的同一颜色方块的数目用一个数表示。
例如,9 122233331表示为
4 1 2 3 1
1 3 4 1
游戏时,你可以任选一个区域消去。设这个区域包含的方块数为x,则将得到x^2个分值。方块消去之后,其余的方块就会竖直落到底部或其他方块上。而且当有一列方块被完全消去时,其右边的所有方块就会向左移一格。Jimmy希望你能找出得最高分的最佳方案,你能帮助他吗?
输入格式
第一行包含一个整数m(1<=m<=50),表示同颜色方块区域的数目。第二行包含m个数,表示每个方块的颜色(1到m之间的整数)。
输出格式
仅一个整数,即最高可能得分。
输入输出样例
输入
4
1 2 3 1
1 3 4 1
输出
29
解析
首先定义状态:dp[l][r][k] 表示从l到r合并起来,同时后面还有k个和这个同色的方块能获取的最大值。
这个需要分情况dp:
首先如果l == r 直接返回(len[r] + k)2 即可
然后直接炸掉后面的,收益就是dp[l][r - 1][0] + (len[r] + k)2
再然后就是正常合并,从l到r枚举断点i,在他本身和dp[l][i][len[r] + k] + dp[i + 1][r - 1][0]取最大值
代码
#include<bits/stdc++.h>
using namespace std;
long long co[10001];
long long len[100001];
long long n;
long long dp[101][101][301];
long long dfs(long long l,long long r,long long k){
if(l > r) return 0;
if(l == r) return dp[l][r][k] = (len[r] + k) * (len[r] + k);
if(~dp[l][r][k]) return dp[l][r][k];
dp[l][r][k] = (len[r] + k) * (len[r] + k) + dfs(l,r - 1,0);
for(int i = l; i < r; i++){
if(co[i] == co[r]) dp[l][r][k] = max(dp[l][r][k],dfs(l,i,len[r] + k) + dfs(i + 1,r - 1,0));
}
return dp[l][r][k];
}
int main()
{
scanf("%lld" ,&n);
for(int i = 1;i <= n; i++){
scanf("%lld" ,&co[i]);
}
for(int i = 1;i <= n; i++){
scanf("%lld" ,&len[i]);
}
memset(dp,-1,sizeof(dp));
dfs(1,n,0);
printf("%lld" ,dp[1][n][0]);
return 0;
}

浙公网安备 33010602011771号