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

矩阵连乘

题目描述

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

解题代码

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]最优解对应的划分kvector<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) { // 矩阵链左端点iint j = i + len - 1; // 矩阵链右端点jfor (int k = i; k <= j - 1; ++k) { // 划分点kint 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]的LCSvector<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) { // 多边形顶点序列长度lenfor (int i = 0; i + len - 1 < n; ++i) { // 顶点序列左端点iint j = i + len - 1; // 顶点序列右端点jdp[i][j] = INT32_MAX;for (int k = i + 1; k < j; ++k) { // 划分点kint 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] : 0dp[0][j] = values[0];}for (int i = 1; i < n; ++i) { // 可选商品0~ifor (int j = 1; j <= c; ++j) { // 背包容量jdp[i][j] = dp[i - 1][j]; // 不选择商品iif (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和pSumdp[i][i - 1] = pLeaves[i - 1];pSum[i][i - 1] = pLeaves[i - 1];}for (int len = 1; len <= n; ++len) { // 结点序列长度lenfor (int i = 1; i + len - 1 <= n; ++i) { // 序列左端点iint j = i + len - 1; // 序列右端点jpSum[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.hqwc.cn/news/109284.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全中的欺骗攻击与防御技术

在Internet上计算机之间相互进行的交流建立在两个前提之下&#xff1a;认证、信任。 认证是网络上的计算机用于相互间进行识别的一种鉴别过程&#xff0c;经过认证的过程&#xff0c;获准相互交流的计算机之间就会建立起相互信任的关系。信任和认证具有逆反关系&#xff0c;即…

爬虫逆向实战(33)-某联社数据(webpack)

一、数据接口分析 主页地址&#xff1a;某联社 1、抓包 通过抓包可以发现数据接口是/nodeapi/telegraphList 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有一个sign加密参数 请求头是否加密&#xff1f; 无 响应是否加密&#x…

性能监控-grafana+prometheus+node_exporter

Prometheus是一个开源的系统监控和报警工具。它由SoundCloud开发并于2012年发布&#xff0c;后来成为了一个独立的开源项目&#xff0c;并得到了广泛的应用和支持。 Prometheus的主要功能包括采集和存储各种系统和应用程序的监控数据&#xff0c;并提供强大的查询语言PromQL来…

【云原生】kubectl常用命令大全

目录 一、资源管理方法 kubectl 的命令大全 二、 kubectl常用命令大全 2.2 项目的生命周期&#xff1a;创建-->发布-->更新-->回滚-->删除 1、创建 kubectl create命令 2、发布 kubectl expose命令 3、更新 kubectl set 4、回滚 kubectl rollou…

线性代数的本质(九)——二次型与合同

文章目录 二次型与合同二次型与标准型二次型的分类度量矩阵与合同 二次型与合同 二次型与标准型 Grant&#xff1a;二次型研究的是二次曲面在不同基下的坐标变换 由解析几何的知识&#xff0c;我们了解到二次函数的一次项和常数项只是对函数图像进行平移&#xff0c;并不会改变…

Qt 围炉札记

文章目录 一、Qt 调试二、vscode 与 Qt1、安装插件&#xff1a;2、设置中配置插件 一、Qt 调试 【Qt调试技巧】Profile配置使用及一些坑 QT运行时的Debug、Release、Profile选项区别 Qt Creator release版本进行调试 【Qt调试技巧】如何在Release下调试Qt程序&#xff1f; …

STM32 CAN使用记录:bxCAN基础通讯

文章目录 目的关键配置与代码轮询方式中断方式收发测试 示例链接总结 目的 CAN是非常常用的一种数据总线&#xff0c;被广泛用在各种车辆系统中。这篇文章将对STM32中CAN的使用做个示例。 CAN的一些基础介绍可以参考下面文章&#xff1a; 《CAN基础概念》https://blog.csdn.n…

node 之 express 框架(初级)

一、express 热更新 1、安装扩展 npm install node-dev -D2、在根目录下的 package.json 文件中进行配置 3、之后的启动执行下面的命令即可 npm run dev二、mvc中的 模板引擎 1、ejs模板引擎的安装 npm install ejs -s2、在根目录下的app.js文件中配置 app.set(view engin…

Python中使用item()方法遍历字典的例子

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 这篇文章主要介绍了Python中使用item()方法遍历字典的例子, for…in这种是Python中最常用的遍历字典的方法了,需要的朋友可以参考下 Python字典的遍历方法有好几种&#xff0c;其中一种是for…in&#xff0c;这个我就…

vue学习之条件渲染

条件渲染 用于控制组件显示创建 demo6.html,内容如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

Minio入门系列【1】Windows/Linux/K8S单机部署Minio

1 Minio简介 MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等&#xff0c;而一个对象文件可以是任意大小&…

计算机网络:三次握手与四次挥手

摘取作者&#xff1a;拓跋阿秀 三次握手 三次握手&#xff08;Three-way Handshake&#xff09;其实就是指建立一个TCP连接时&#xff0c;需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后…