添加括号题解(兼平行四边形优化dp小记)

本人做了这道题后发现这道题不仅涉及到括号匹配递归,又涉及刚学的平行四边形优化dp,于是来写题解。

小记

平行四边形优化是个玄学,主要看题感和运气,你觉得是就是,可以用这种优化的题主要有以下特征:

dp[i][j]=max/min(dp[i][j],dp[k][j-1]+w[k+1][i]);(k为1~n)

dp[i][j]=max/min(dp[i][j],dp[i][k]+dp[k+1][j]);(k为1~n)

如果该题符合平行四边形优化特点,k在(s[i-1][j]~s[i][j+1])之间。(s[i][j]表示i~j的最优分割点)。

题目描述

见洛谷(P2308 添加括号)

题目理解

我不说大家也看得出来,是经典的合并石子题,符合上方第二个dp,又用到每次加括号的位置,所以本来就会记录s[i][j]的平行四边形优化当然是首选,再用递归输出括号。

注:该题分割线尽量靠右,括号就会在左。(1,2,4,1,2)的最优解是[(((1+2)+4)+(1+2))]而非[((1+2)+(4+(1+2)))]

题目代码

#include<cstdio> 
#include<algorithm> 
using namespace std;
#define M (20 + 5)
#define LL int
inline void read(LL &x) 
{ 
    x=0;LL f=1;char c=getchar(); 
    while(c<'0'||c>'9') 
    { 
        if(c=='-') 
            f=0-f; 
        c=getchar(); 
    } 
    while(c>='0'&&c<='9') 
    { 
        x=x*10+c-'0'; 
        c=getchar(); 
    } 
    x*=f; 
    return ; 
}
inline void write(int x)
{
	if(x<10)
		putchar(x+'0');
	else{
		write(x/10);
		putchar(x%10+'0');
	}
	return ;
}
int n,a[M],v,ans,tp,dp[M][M],s[M][M],sum[M];
void dfs1(int l,int r)
{
	if(l==r)
	{
		write(a[l]);
		return ;
	}
	putchar('(');
	dfs1(l,s[l][r]);
	putchar('+');
	dfs1(s[l][r]+1,r);
	putchar(')');
	return ;
}
void dfs2(int l,int r)
{
	if(l==r)
		return ;
	dfs2(l,s[l][r]);
	dfs2(s[l][r]+1,r);
	write(sum[r]-sum[l-1]);
	if(!(l==1&&r==n))
	putchar(' ');
	return ;
}
int main()
{
    read(n);
    for(int i=1;i<=n;i++)
        read(a[i]),s[i][i]=i,sum[i]=a[i]+sum[i-1];//尺取法
    for(int len=2;len<=n;len++)
    	for(int l=1;l+len-1<=n;l++)
    	{
    		int r=l+len-1;
    		dp[l][r]=0x3f3f3f3f;
    		for(int k=s[l][r-1];k<=s[l+1][r]&&k<r;k++)
    			if(dp[l][r]>=dp[l][k]+dp[k+1][r])
    			{
    				dp[l][r]=dp[l][k]+dp[k+1][r];
    				s[l][r]=k;
				}
			if(dp[l][r]==0x3f3f3f3f)
				dp[l][r]=0;
			dp[l][r]+=sum[r]-sum[l-1];
		}
	dfs1(1,n);
    putchar('\n');
    write(dp[1][n]);
    putchar('\n');
    dfs2(1,n);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值