算法分析与设计编程题 动态规划

news2025/5/26 2:56:06

矩阵连乘

题目描述

请添加图片描述
在这里插入图片描述

解题代码

void printOptimalParens(vector<vector<int>>& partition, int i, int j) {
	if (i == j) cout << "A" << i; // 单个矩阵,无需划分
	else {
		cout << "(";
		printOptimalParens(partition, i, partition[i][j]);
		printOptimalParens(partition, partition[i][j] + 1, j);
		cout << ")";
	}
}

// nums[i]: nums[0]为矩阵A1的行数,nums[i](i >= 1)表示矩阵Ai的列数
// 如输入为 nums = { 30,35,15,5,10,20,25 },代表矩阵行列数如下:
// A1: 30 * 35, A2: 35 * 15, A3: 15 * 5, A4: 5 * 10, A5: 10 * 20, A6: 20 * 25
int matrixChainOrder(vector<int>& nums) {
	int n = nums.size() - 1;
	// dp[i][j]表示矩阵链A[i~j]的最优解
	vector<vector<int>> dp(n + 1, vector<int>(n + 1, INT32_MAX));
	// partition[i][j]表示矩阵链A[i~j]最优解对应的划分k
	vector<vector<int>> partition(n + 1, vector<int>(n + 1));
	for (int i = 1; i <= n; ++i) {
		dp[i][i] = 0; // 矩阵链长度为1时,最优解为0
	}
	for (int len = 2; len <= n; ++len) { // len为矩阵链长度
		for (int i = 1; i + len - 1 <= n; ++i) { // 矩阵链左端点i
			int j = i + len - 1; // 矩阵链右端点j
			for (int k = i; k <= j - 1; ++k) { // 划分点k
				int sum = dp[i][k] + dp[k + 1][j] + nums[i - 1] * nums[k] * nums[j];
				if (sum < dp[i][j]) { // 更新最优解
					dp[i][j] = sum;
					partition[i][j] = k;
				}
			}
		}
	}
	printOptimalParens(partition, 1, n); // 打印最优方案
	return dp[1][n];
}

最长公共子序列

题目描述

在这里插入图片描述

解题代码

void printLCS(const string& text1, vector<vector<char>>& dir, int i, int j) {
    if (i == 0 || j == 0) return;
    if (dir[i][j] == 'S') { // 向左上移动
        printLCS(text1, dir, i - 1, j - 1);
        cout << text1[i - 1]; // 递归后再输出字符,以实现反向
    }
    else if (dir[i][j] == 'U') { // 向上移动
        printLCS(text1, dir, i - 1, j);
    }
    else { // 向左移动
        printLCS(text1, dir, i, j - 1);
    }
}

int longestCommonSubsequence(string text1, string text2) {
    int m = text1.size(), n = text2.size();
    // dp[i][j]表示text1[0~i-1]和text2[0~i-1]的LCS
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    // dir[i][j]记录得到LCS的移动方向,以便构造最优解
    vector<vector<char>> dir(m + 1, vector<char>(n + 1, '*'));
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (text1[i - 1] == text2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
                dir[i][j] = 'S';
            }
            else if (dp[i - 1][j] >= dp[i][j - 1]) {
                dp[i][j] = dp[i - 1][j];
                dir[i][j] = 'U';
            }
            else {
                dp[i][j] = dp[i][j - 1];
                dir[i][j] = 'L';
            }
        }
    }
    printLCS(text1, dir, m, n); // 构造最优解
    return dp[m][n];
}

最大子段和

题目描述

在这里插入图片描述

解题代码

分治法

int dividedMaxSubSum(vector<int>& nums, int left, int right) {
	if (left == right) return nums[left]; // 单个元素最大子段和为该元素的值
	int mid = left + (right - left) / 2;
	int lSum = dividedMaxSubSum(nums, left, mid); // 划分左端子数组的最大子段和
	int rSum = dividedMaxSubSum(nums, mid + 1, right); // 划分右端子数组的最大子段和
    // 计算穿过划分点的子数组左端的最大子段和
    int midL = 0, maxMidL = INT32_MIN;
	for (int i = mid; i >= left; --i) {
		midL += nums[i];
		maxMidL = max(maxMidL, midL);
	}
    // 计算穿过划分点的子数组右端的最大子段和
	int midR = 0, maxMidR = INT32_MIN;
	for (int i = mid + 1; i <= right; ++i) {
		midR += nums[i];
		maxMidR = max(maxMidR, midR);
	}
    // 子数组的最大子段和为三者之间最大的一个
	return max(maxMidL + maxMidR, max(lSum, rSum));
}

int maxSubSum(vector<int>& nums) {
	int n = nums.size();
	return dividedMaxSubSum(nums, 0, n - 1);
}

动态规划

int maxSubSum(vector<int>& nums) {
	int res = 0, sum = 0;
	for (int i = 0; i < nums.size(); ++i) {
		if (sum > 0) {
			sum += nums[i];
		}
        // 当前累计总和小于零,则包含该部分的子段必不可能为最大子段,可根据反证法证明:
        // 假设子段S为最大子段,且其包含总和为负的前缀子段s1,则将该前缀子段删去后得到的新子段S'的子段和必定大于S,与假设矛盾
		else { 
			sum = nums[i];
		}
		res = max(res, sum);
	}
	return res;
}

凸多边形最优三角剖分

题目描述

在这里插入图片描述
在这里插入图片描述

解题代码

int minScoreTriangulation(vector<int>& values) {
    int n = values.size();
    vector<vector<int>> dp(n, vector<int>(n, 0));
    for (int len = 3; len <= n; ++len) { // 多边形顶点序列长度len
        for (int i = 0; i + len - 1 < n; ++i) { // 顶点序列左端点i
            int j = i + len - 1; // 顶点序列右端点j
            dp[i][j] = INT32_MAX;
            for (int k = i + 1; k < j; ++k) { // 划分点k
                int cost = dp[i][k] + dp[k][j] + values[i] * values[j] * values[k];
                dp[i][j] = min(dp[i][j], cost); 
            }
        }
    }
    return dp[0][n - 1];
}

0-1背包问题

题目描述

在这里插入图片描述

解题代码

int knapsack01(vector<int>& weights, vector<int>& values, int c) {
	int n = weights.size();
    // dp[i][j]表示可选商品为0~i,背包容量为j情况下的最优解
	vector<vector<int>> dp(n, vector<int>(c + 1, 0));
	for (int j = weights[0]; j <= c; ++j) {
		// 若i=0,即可选商品只有0,此时最优解为:能否装下商品0 ? values[0] : 0
        dp[0][j] = values[0];
	}
	for (int i = 1; i < n; ++i) { // 可选商品0~i
		for (int j = 1; j <= c; ++j) { // 背包容量j
			dp[i][j] = dp[i - 1][j]; // 不选择商品i
			if (j >= weights[i]) { // 若j >= weight[i],则可选择商品i
                // 取两种情况(选择或不选择商品i)下的最优解
				dp[i][j] = max(dp[i][j], dp[i - 1][j - weights[i]] + values[i]);
			}
		}
	}
	return dp[n - 1][c];
}

最优二叉搜索树

题目描述

在这里插入图片描述

解题代码

// pNonLeaves[i](i >= 1)表示非叶结点i的搜索概率,pLeaves[i](i >= 0)表示叶子结点i的搜索概率
// 如输入为 pNonLeaves = { 0.0,0.15,0.10,0.05,0.10,0.20 }
// 表示非叶结点i的搜索概率p[1~5] = [ 0.15,0.10,0.05,0.10,0.20 ](原数组首个0为占位用,无实际含义)
// 如输入为 pLeaves = { 0.05,0.10,0.05,0.05,0.05,0.10 }
// 表示非叶结点i的搜索概率q[0~5] = [ 0.05,0.10,0.05,0.05,0.05,0.10 ]
double optimalBST(vector<double>& pNonLeaves, vector<double>& pLeaves) {
    int n = pNonLeaves.size() - 1; // 非叶节点的个数n
    // dp[i][j]表示根据结点序列pNonLeaves[i~j]和pLeaves[i~j]构成的最优解(子树)
    // dp[i][i-1]代表只含有叶结点i-1的子树(不含非叶节点)
    vector<vector<double>> dp(n + 2, vector<double>(n + 1, DBL_MAX));
    // root[i][j]表示dp[i][j]对应的子树的根节点,可根据其构造最优二叉搜索树
    vector<vector<int>> root(n + 1, vector<int>(n + 1));
    // pSum[i][j]表示结点序列pNonLeaves[i~j]和pLeaves[i~j]的概率总和
    vector<vector<double>> pSum(n + 2, vector<double>(n + 1));
    for (int i = 1; i <= n + 1; ++i) { // 初始化dp和pSum
        dp[i][i - 1] = pLeaves[i - 1];
        pSum[i][i - 1] = pLeaves[i - 1];
    }
    for (int len = 1; len <= n; ++len) { // 结点序列长度len
        for (int i = 1; i + len - 1 <= n; ++i) { // 序列左端点i
            int j = i + len - 1; // 序列右端点j
            pSum[i][j] = pSum[i][j - 1] + pNonLeaves[j] + pLeaves[j]; // 递推计算结点序列区间概率和
            for (int r = i; r <= j; ++r) { // 将非叶结点r选作根节点
                double cost = dp[i][r - 1] + dp[r + 1][j] + pSum[i][j]; // 该情况下的搜索代价
                if (cost < dp[i][j]) { // 更新最优解
                    dp[i][j] = cost;
                    root[i][j] = r;
                }
            }
        }
    }
    return dp[1][n];
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1010451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

异步FIFO设计的仿真与综合技术(3)

概述 本文主体翻译自C. E. Cummings and S. Design, “Simulation and Synthesis Techniques for Asynchronous FIFO Design 一文&#xff0c;添加了笔者的个人理解与注释&#xff0c;文中蓝色部分为笔者注或意译。前文链接&#xff1a; 异步FIFO设计的仿真与综合技术&#xf…

29.Xaml TreeView控件---->树形控件,节点的形式显示数据

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

栈和队列讲解

栈和队列 栈和队列3.1 栈和队列的定义和特点3.2 案例引用3.3 栈的顺序表示和实现3.4 栈的链式表示和实现3.5 队列的顺序表示和实现3.6 队列的链式表示和实现 3.1 栈和队列的定义和特点 栈 (stack) 是限定仅在表尾进行插入或删除操作的线性表。 因此&#xff0c; 对栈来说&…

树莓派4B使用Docker部署SpringBoot项目——(一)树莓派安装docker

使用Shell7连接树莓派&#xff0c;命令行执行安装命令&#xff0c;等待安装成功即可。 apt install docker.io执行docker version查看docker版本信息。 其他docker命令。 docker images 查看镜像 docker ps -a 查看所有容器 docker ps 查看运行的容器

社区分享|MeterSphere变身“啄木鸟”,助力云帐房落地接口自动化测试

云帐房网络科技有限公司&#xff08;以下简称为“云帐房”&#xff09;成立于2015年3月&#xff0c;以“成为最值得信赖的税务智能公司”为愿景&#xff0c;运用人工智能、大数据等互联网技术&#xff0c;结合深厚的财税行业服务经验&#xff0c;为代账公司和中大型企业提供智能…

Linux中使用Docker安装ElasticSearch7.10.x集群

使用Docker安装ElasticSearch7.10.x单节点请访问这里 一、集群环境说明 服务器IP地址192.168.137.1&#xff0c;192.168.137.2&#xff0c;192.168.137.3 二、前期准备 1. 拉取镜像 docker pull elasticsearch:7.10.12. 首先需要创建一个用于生成秘钥的初始容器&#xff0…

一体化研发协作赋能平台:Apipost

作为一款专为程序员打造的API管理工具&#xff0c;Apipost也成为开发人员圈子里的一款热门工具。Apipost拥有强大的功能和便捷操作性&#xff0c;这也让许多开发者爱不释手。那么&#xff0c;Apipost到底有哪些吸引人的特点呢&#xff1f;本文将为您详细介绍。 统一API管理 Ap…

qt 移植到vs后,常见问题汇总????

1.第一次在VS中编译QT项目&#xff0c;因为在MinGW中不能编译带有qtwebengine的程序&#xff0c;因为这个引擎使用的google浏览器的内核&#xff0c;据QT官方的说法&#xff1a;google不喜欢MinGW,所以QT5.5以后的版本中带有这个模块的的部分将无法编译通过&#xff0c;我们只能…

《银河麒麟高级服务器操作系统V10》使用

一言而论&#xff1a;讲了麒麟服务器V10的基本使用&#xff0c;包括终端、VNC 文章目录 前言基本架构环境硬件环境软件环境 麒麟安装步骤1.在宿主机上安装好VM&#xff0c;并且激活2.使用VM创建虚拟机3.启动虚拟机 终端常用点VNC的使用麒麟上安装VNC服务器Windows上安装VNC客户…

在ie浏览器下解决pdfjs插件思源宋体字体部分无法识别问题

pdf文件正常 利用pdfis渲染出来就成这样了 查看了思源宋体是2017年发布,pdf版本是1.10.88 &#xff0c;推测可能由于版本问题部分字体映射没有&#xff0c;去官网拷贝了几个版本&#xff0c;在本地启服务测试了几个&#xff0c;为了兼顾ie浏览器兼容 &#xff0c;选择了2.0.94…

JVM参数配置

一、堆内存相关配置 复制代码 设置堆初始值 指令1&#xff1a;-Xms2g 指令2&#xff1a;-XX:InitialHeapSize2048m ​ ​ 设置堆区最大值 指令1&#xff1a;-Xmx2g 指令2&#xff1a; -XX:MaxHeapSize2048m ​ ​ 缩小堆内存的时机 -XX:MaxHeapFreeRatio70//堆内存…

视频怎么抠图换背景,怎么把视频后面的背景换掉?

视频中的背景可以直接影响整个视频的观感&#xff0c;有时候我们需要更换背景来达到更好的效果。而如何更换背景呢&#xff1f; 在视频制作中&#xff0c;更换视频背景可以为视频添加更好的视觉效果&#xff0c;增强观赏性和吸引力。例如&#xff0c;在拍摄一个演讲视频时&…

C++之打印编译全过程(二百一十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

驱动开发--汇总

一&#xff0c;【驱动相关概念】 1&#xff0c;什么是驱动 能够驱使硬件实现特定功能的软件代码 根据驱动程序是否依赖于系统内核将驱动分为裸机驱动和系统驱动 2&#xff0c;逻辑驱动和系统驱动的区别 裸机驱动&#xff1a;编写的驱动代码中没有进行任何内核相关API的调用…

小程序实现一个 倒计时组件

小程序实现一个 倒计时组件 需求背景 要做一个倒计时&#xff0c;可能是天级别&#xff0c;也可能是日级别&#xff0c;时级别&#xff0c;而且每个有效订单都要用&#xff0c;就做成组件了 效果图 需求分析 需要一个未来的时间戳&#xff0c;或者在服务度直接下发一个未来…

LeetCode-热题100-笔记-day23

104. 二叉树的最大深度https://leetcode.cn/problems/maximum-depth-of-binary-tree/ 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,1…

leetcode 332. Reconstruct Itinerary(重构行程)

有一些票tickets, tickets[ i ] [from, to], 每个出发到达城市名字都是3个大写英文字母&#xff0c; 同一个出发城市时&#xff0c;优先去字母顺序较小的到达城市。 必须先从“JFK”出发。 每个ticket必须用且只用一次&#xff0c;所有ticket一定会形成至少一个有效的行程&…

重建大师提交空三后引擎状态是等待,怎么开启?

答&#xff1a;图片中这是在自由网空三阶段&#xff0c;整个AT都是等待中&#xff0c;可以修改任务目录和监控目录看一下&#xff0c;先设置引擎&#xff0c;再提交空三。

【Unity】万人同屏, 从入门到放弃之——多线程RVO避障

不使用Dots能否实现海量物体同屏&#xff1f;很多场面宏大的游戏&#xff0c;尤其是Rougelike游戏&#xff0c;动辄成千上万满屏怪&#xff0c;割草清屏的快感酣畅淋漓&#xff0c;所以这类游戏非常火爆&#xff0c;然鹅是怎么做到的呢&#xff1f; 首先&#xff0c;海量移动物…

CRC(循环冗余校验码的校验方法)

5个关键点&#xff1a; 1.信息码&#xff1a;即给出要校验的二进制码 2.生成多项式&#xff1a;一般多项式会给&#xff0c;从最高位的指数位数就可以得到有几个校验码&#xff1b;如果没给多项式&#xff0c;肯定会给个多项式二进制码&#xff0c;根据它来推就行&#xff08;…