20180614 DP4训练 K - Blocks(区间DP)

题意:

有一串长度为n的块,每次可以消去x个连续的相同的块,并且获得的值为x*x,问消去所有快能获得的最大价值?

思路:

区间DP。一开始没搞明白这个题目什么意思,理解错了,其实把区间分割完之后在合并,不是最优的,因此不能单独考虑每个区间。在每个区间(x,y)里面,在i的位置,我们只需要统计他的前面有多少相同的块,dp[i][j][k]其中k表示i前面的相同得块的个数,dp【i】【j】【k】整体即表示消去前面k个颜色相同的块和区间【i,j】里的块可以获得的最大价值。状态转移方程为:

dp[i][j][k] = max(dp[i+1][j][k] + (1 + k) * (1 + k), dp[l][j][k+1] + dp[i+1][l-1][0]);

代码:

#include <bits/stdc++.h>
using namespace std;
#define M 250
#define INF ox3f3f3f3f
int a[M];
int dp[M][M][M];
int dfs(int i,int j,int k)  //DFS区间
{
    if(dp[i][j][k]!=-1)
        return dp[i][j][k];  //记忆化保存
    if(i>j){                 //i>j不符合条件
        dp[i][j][k]=0;
        return 0;
    }
    dp[i][j][k]=dfs(i+1,j,0)+(1+k)*(1+k);
    for(int l=i+1;l<=j;l++)
    {
        if(a[l]==a[i])
            dp[i][j][k]=max(dp[i][j][k],dfs(l,j,k+1)+dfs(i+1,l-1,0));  //关键状态方程
    }
    return dp[i][j][k];
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(dp,-1,sizeof(dp));
        printf("Case %d: %d\n",cas++,dfs(1,n,0));
    }
    return 0;
}

  • dp [i] [j] [k] = max(dp [i加1] [j] [k]加(1加k)*(1加k),dp [1] [j] [k加1]加上dp [i plus 1] [l-1] [0]);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值