首页 > 其他分享 >添加括号(区间dp+求方案)

添加括号(区间dp+求方案)

时间:2024-05-26 18:02:52浏览次数:18  
标签:10 遍历 中间 int 括号 添加 dp 这道题

添加括号

题目背景

给定一个正整数序列a(1),a(2),…,a(n),(1<=n<=20)

不改变序列中每个元素在序列中的位置,把它们相加,并用括号记每次加法所得的和,称为中间和。

例如:

给出序列是4,1,2,3。

第一种添括号方法:

((4+1)+(2+3))=((5)+(5))=(10)

有三个中间和是5,5,10,它们之和为:5+5+10=20

第二种添括号方法

(4+((1+2)+3))=(4+((3)+3))=(4+(6))=(10)

中间和是3,6,10,它们之和为19。

题目描述

现在要添上n-1对括号,加法运算依括号顺序进行,得到n-1个中间和,求出使中间和之和最小的添括号方法。

输入格式

共两行。 第一行,为整数n。(1< =n< =20) 第二行,为a(1),a(2),…,a(n)这n个正整数,每个数字不超过100。

输出格式

输出3行。 第一行,为添加括号的方法。 第二行,为最终的中间和之和。 第三行,为n-1个中间和,按照从里到外,从左到右的顺序输出。

样例 #1

样例输入 #1

4
4 1 2 3

样例输出 #1

(4+((1+2)+3))
19
3 6 10

提示

范围在题目上有说明。

思路

这道题的第二小问你不觉得很熟悉吗,它不就是合并果子的板子小题吗?因此我们这道题用区间dp来做,只不过这道题相比那道题多了求方案。对于这样的,我们可以类似二叉树的中序遍历那样来找方案。

具体怎么找方案:

  • 我们可以在区间dp开始枚举断点的时候,如果状态已经更新了,我们就可以记录此时状态的断点。
  • 然后我们采取中序遍历的板子来写出答案。

代码

//这道题如果不求方案的话就是石子合并了
//所以,这道题就是很经典的区间合并,只不过要求方案
//对于题目的第一第三问,我们可以利用树的方式遍历(也就是中序遍历)

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 25;

int f[N][N];
int n;
int w[N];
int s[N];//前缀和
int pre[N][N];
int ans[N],cnt;

void print(int x,int y){
    if(x==y){
        cout<<s[x]-s[x-1];
        return;
    }
    
    cout<<"(";
    print(x,pre[x][y]);
    cout<<"+";
    print(pre[x][y]+1,y);
    cout<<")";
    ans[++cnt]=s[y]-s[x-1];
}

int main(){
    cin>>n;
    
    memset(f,0x3f,sizeof f);
    
    for(int i=1;i<=n;i++){
        cin>>w[i];
        s[i]=s[i-1]+w[i];
        f[i][i]=0;
    }
    
    for(int len=2;len<=n;len++){
        for(int l=1;l+len-1<=n;l++){
            int r=l+len-1;
            for(int k=l;k<r;k++){//为什么不能等于r,因为必须要有两份
                // f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
                if(f[l][k]+f[k+1][r]+s[r]-s[l-1]<f[l][r]){
                    f[l][r]=f[l][k]+f[k+1][r]+s[r]-s[l-1];
                    pre[l][r]=k;//记录分界点
                }
            }
        }
    }
    print(1,n);//中序遍历
    cout<<endl;
    cout<<f[1][n]<<endl;
    for(int i=1;i<=cnt;i++){
        cout<<ans[i]<<' ';
    }
    return 0;
}

标签:10,遍历,中间,int,括号,添加,dp,这道题
From: https://blog.csdn.net/m0_60738889/article/details/139201078

相关文章

  • 赛克 1530(环形dp)
    赛氪OJ-专注于算法竞赛的在线评测系统(saikr.com)枚举第一张卡片是由法力值降低还是法力值上升得到的,一共有4种情况,d[i][j][0]表示第i个卡牌选第j个法力值并且上一个卡牌的法力值大于j的所获得的前i个卡牌的最大运气值;d[i][j][1]表示第i个卡牌选第j个法力值并且上一个卡牌的法力......
  • [Unity] 添加新建Lua脚本选项
    Unity添加新建Lua脚本选项最近学习Unity的XLua热更新框架的时候,会经常需要创建新的Lua脚本。然而,Unity本身不支持直接创建.lua后缀的文件,所以每次都必须手动在外部打开文件夹创建。为了提高效率,就需要在Unity新建文件的菜单中添加了一个“新建Lua脚本”的选项。并且,要达到和“......
  • vb.net 利用APi 、句柄,通过GetWindowThreadProcessId 获得窗口所在进程ID和线程ID 结
    '''<summary>'''声明'''</summary>'''<paramname="hwnd"></param>'''<paramname="lpdwProcessId"></param>......
  • 蓝桥杯备赛——DP【python】
    一、小明的背包1试题链接:https://www.lanqiao.cn/problems/1174/learning/问题描述输入实例52016253851533输出示例37问题分析这里我们要创建一个DP表,DP(i,j)表示处理到第i个物品时消耗j体积。这样我们在输入数据时可以直接进行操作。对于每一个dp[i][j]我......
  • P1944 最长括号匹配
    链接:https://www.luogu.com.cn/problem/P1944题目:思路:注意题目里说的:1.(),[]是括号匹配的字符串。2.若A是括号匹配的串,则(A),[A]是括号匹配的字符串。3.若A,B是括号匹配的字符串,则AB也是括号匹配的字符串。所以设dp[i]是以i结尾的最长匹配字符串的长度,那么更新状态方程可以......
  • hi.选课(树形DP)
    [CTSC1997]选课(树形DP)题目描述在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N......
  • .NET Core中给上传图片的添加水印
    一.安装System.Drawing.Common库工具->NuGet包管理->程序包管理控制台输入命令Install-PackageSystem.Drawing.Common二.代码案例实现usingMicrosoft.AspNetCore.Http;usingMicrosoft.AspNetCore.Mvc;usingSystem.Drawing;usingSystem.Drawing.Imaging;usingSy......
  • EasyCVR视频管理平台存在任意用户添加漏洞
    漏洞描述攻击者可以通过发送特定的POST请求,利用未授权访问的接口'/api/v1/adduser',在系统中添加任意用户,并将其设置为管理员角色。fofaapp="EasyCVR-视频管理平台"pocpassword为md5加密POST/api/v1/adduserHTTP/1.1Host:xxx.xxx.xxx.xxxContent-Type:application/x-ww......
  • Java ThreadPoolExecutor
    ThreadPoolExecutor?ThreadPoolExecutor是什么,先拆开来看,ThreadPoolAndExecutor?那ThreadPool是什么?Executor又是什么?Executor:任务执行者,只定义了一个execute方法,接收一个Runable参数。publicinterfaceExecutor{voidexecute(Runnablecommand);}ThreadPool:可以缓存......
  • 区间DP
    区间DP区间DP的一般表达式:枚举区间长度枚举区间起点计算区间终点枚举区间断点P1220关路灯状态dp[i][j][0/1]表示区间[i,j]的路灯全关掉且站在i或j处的最小功耗答案min(dp[1][n][0],dp[1][n][1])状态转移for(intlen=2;len<=n;len++){ for(inti=1;i+len-1<=n;i++){......