P1291-添加括号(区间dp)

本文介绍了一种使用区间动态规划(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个中间和,按照从里到外,从左到右的顺序输出。


一道很有价值的区间dp,一共包含了3个子问题;首先用区间dp求出f[i][j]及i-j之间最小的累加和,很显然有:

for(int len = 2; len <= n; ++len) {
        for(int l = 1; l <= n - len + 1; ++l) {
            int r = l + len - 1;
            for(int i = l; i < r; ++i) 
                f[l][r] = min(f[l][r], f[l][i] + f[i + 1][r]); 
            f[l][r] += sum[r] - sum[l - 1]; 
        }
    }

接着用dfs枚举区间来求出括号的方案,同时求出所有区间的和,用ans作为序号便于输出,这样就A掉了,个别细节需要注意,切切切~~

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10;

inline int read() {
    int x = 0, ff = 1; char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') ff = -1;
        ch = getchar();
    }
    while(isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * ff;
}

inline void write(int x) {
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int n, ans, a[MAXN], sum[MAXN], f[MAXM][MAXM];
priority_queue < pair < int, int > > q;

void dfs(int l, int r) {
    if(l == r) {
        write(a[l]);
        return ;
    }
    for(int i = r; i >= l; --i) { // 倒序,为了使方案等效时,以括弧靠左为优先~ 
        if(f[l][i] + f[i + 1][r] + sum[r] - sum[l - 1] == f[l][r]) { // 好好思考~ 
            putchar('(');
            dfs(l, i);
            putchar('+');
            dfs(i + 1, r);
            putchar(')');
            q.push(make_pair(-(++ans), sum[r] - sum[l - 1]));
            return ;
        }
    }
}

int main() {
    memset(f, 0x3f, sizeof(f)); 
    n = read(); 
    for(int i = 1; i <= n; ++i) {
        a[i] = read();
        f[i][i] = 0; 
        sum[i] = sum[i - 1] + a[i];
    }
    for(int len = 2; len <= n; ++len) {
        for(int l = 1; l <= n - len + 1; ++l) {
            int r = l + len - 1;
            for(int i = l; i < r; ++i) 
                f[l][r] = min(f[l][r], f[l][i] + f[i + 1][r]); 
            f[l][r] += sum[r] - sum[l - 1]; 
        }
    }
    dfs(1, n); 
    putchar('\n');
    write(f[1][n]);
    putchar('\n');
    while(!q.empty()) {
        int x = q.top().second; q.pop();
        write(x); 
        putchar(' ');
    } 
    return 0; 
}

 

转载于:https://www.cnblogs.com/AK-ls/p/10695483.html

【3D应力敏感度分析拓扑优化】【基于p-范数全局应力衡量的3D敏感度分析】基于伴随方法的有限元分析和p-范数应力敏感度分析(Matlab代码实现)内容概要:本文档介绍了基于伴随方法的有限元分析与p-范数全局应力衡量的3D应力敏感度分析,并结合拓扑优化技术,提供了完整的Matlab代码实现方案。该方法通过有限元建模计算结构在载荷作用下的应力分布,采用p-范数对全局应力进行有效聚合,避免传统方法中应力约束过多的问题,进而利用伴随法高效求解设计变量对应力的敏感度,为结构优化提供关键梯度信息。整个流程涵盖了从有限元分析、应力评估到敏感度计算的核心环节,适用于复杂三维结构的轻量化与高强度设计。; 适合人群:具备有限元分析基础、拓扑优化背景及Matlab编程能力的研究生、科研人员与工程技术人员,尤其适合从事结构设计、力学仿真与多学科优化的相关从业者; 使用场景及目标:①用于实现高精度三维结构的应力约束拓扑优化;②帮助理解伴随法在敏感度分析中的应用原理与编程实现;③服务于科研复现、论文写作与工程项目中的结构性能提升需求; 阅读建议:建议读者结合有限元理论与优化算法知识,逐步调试Matlab代码,重点关注伴随方程的构建与p-范数的数值处理技巧,以深入掌握方法本质并实现个性化拓展。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值