题解:方块消除

题目

题目描述

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;
}
posted @ 2021-05-13 20:12  24Kmagic  阅读(364)  评论(0)    收藏  举报