杭电oj(1087、1203、1003)题解

DP 即动态规划(Dynamic Programming),是一种通过把原问题分解为相对简单的子问题,并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。以下从几个方面简述动态规划:

基本思想

动态规划的核心在于 “分治” 和 “最优子结构”。它将一个复杂问题分解为一系列相互关联的子问题,通过求解子问题并保存其解,避免对相同子问题的重复求解,从而减少计算量。同时,原问题的最优解可以由子问题的最优解组合而成,这就是最优子结构性质。

适用条件

  • 最优子结构性质:问题的最优解包含其子问题的最优解。即可以通过子问题的最优解推导出原问题的最优解。例如,在背包问题中,对于一个容量为 W 的背包和 n 个物品,要得到其最优装法,可以先考虑容量为 W - w[i]w[i] 为第 i 个物品的重量)的背包和前 n - 1 个物品的最优装法。
  • 子问题重叠性质:在求解过程中,会多次遇到相同的子问题。动态规划通过保存子问题的解,避免了对这些子问题的重复计算,从而提高了效率。比如在斐波那契数列的计算中,直接递归计算会有大量重复的子问题计算,而使用动态规划可以避免这种情况。

求解步骤

  1. 定义状态:明确问题的状态表示,即如何用一个或多个变量来描述子问题。例如,在最长上升子序列问题中,可以定义状态 dp[i] 表示以第 i 个元素结尾的最长上升子序列的长度。
  2. 确定状态转移方程:根据问题的最优子结构性质,找出状态之间的转移关系。状态转移方程描述了如何从子问题的解推导出原问题的解。例如,在最长上升子序列问题中,状态转移方程为 dp[i] = max(dp[j] + 1) (0 <= j < i 且 a[j] < a[i])
  3. 初始化:确定初始状态的值,这些初始状态是问题的边界条件。例如,在斐波那契数列的动态规划求解中,dp[0] = 0dp[1] = 1 就是初始状态。
  4. 计算顺序:根据状态转移方程,确定计算状态的顺序,一般是从简单的子问题开始,逐步求解更复杂的问题。

应用场景

动态规划在很多领域都有广泛的应用,常见的问题包括:

  • 背包问题:如 0 - 1 背包问题、完全背包问题等,用于在一定的约束条件下选择物品,使得总价值最大。
  • 最长公共子序列问题:找出两个序列中最长的公共子序列,在生物信息学、版本控制等领域有应用。
  • 最短路径问题:如 Floyd - Warshall 算法,用于求解图中任意两点之间的最短路径。
  • 资源分配问题:在多个项目或任务之间分配资源,以达到最优的效益。

目录

1087

题目

思路

代码详细步骤

动态规划初始化

状态转移

找出最大值

代码

1203

题目

思路

代码

1003

题目

思路

代码


1087

题目

思路

动态规划算法的核心在于将原问题分解为一系列子问题,并通过求解子问题来得到原问题的解。在这个问题中,我们定义状态 dp[i] 表示以第 i 个元素结尾的最长上升子序列的最大和。通过遍历序列中的每个元素,我们可以根据之前的状态来更新当前状态,最终找出所有状态中的最大值,即为最长上升子序列的最大和。

代码详细步骤

动态规划初始化
  • dp[0]=a[0];:将 dp[0] 初始化为 a[0],因为以第一个元素结尾的最长上升子序列就是它本身,其和就是 a[0]
状态转移
  • 外层循环 for(int i = 1; i < n; i++):遍历数组中的每个元素,从第二个元素开始。
  • dp[i]=a[i];:将 dp[i] 初始化为 a[i],表示以第 i 个元素结尾的最长上升子序列至少包含该元素本身。
  • 内层循环 for(int j = 0; j < i; j++):遍历当前元素 a[i] 之前的所有元素。
  • if(a[i]>a[j]):判断 a[i] 是否大于 a[j],如果满足条件,说明可以将 a[i] 接到以 a[j] 结尾的最长上升子序列后面。
  • dp[i]=max(a[i]+dp[j],dp[i]);:更新 dp[i] 的值,取 a[i] + dp[j] 和 dp[i] 中的最大值。a[i] + dp[j] 表示将 a[i] 接到以 a[j] 结尾的最长上升子序列后面得到的新子序列的和。
找出最大值
  • int maxnum=-1e9;:将 maxnum 初始化为一个较小的值 -1e9,确保后续找到的任何 dp[i] 值都能更新 maxnum
  • for(int i = 0; i < n; i++){ maxnum=max(maxnum,dp[i]); }:遍历 dp 数组,找出其中的最大值。

代码

#include<iostream>
#include<algorithm>
using namespace std;
int dp[1010],a[1010],n; 
int main(){while(cin>>n&&n){for(int i=0;i<n;i++){cin>>a[i];}dp[0]=a[0];for(int i=1;i<n;i++){dp[i]=a[i];for(int j=0;j<i;j++){if(a[i]>a[j]){dp[i]=max(a[i]+dp[j],dp[i]);}}}int maxnum=-1e9;for(int i=0;i<n;i++){maxnum=max(maxnum,dp[i]);}cout<<maxnum<<endl;}return 0;
}

1203

题目

思路

外层循环 for(int i = 0; i < m; i++):遍历每一个物品。

内层循环 for(int j = n; j >= a[i]; j--):从背包的总容量 n 开始,倒序遍历到当前物品的重量 a[i]。倒序遍历是为了保证每个物品只被选择一次,这是 0 - 1 背包问题的常见处理方式。

状态转移方程 dp[j]=max(dp[j],dp[j-a[i]]+prob[i]-dp[j-a[i]]*prob[i]);

dp[j] 表示不选择当前物品 i 时,背包容量为 j 的最大成功概率。

dp[j - a[i]] 表示在不放入当前物品 i 时,背包容量为 j - a[i] 的最大成功概率。

dp[j - a[i]] + prob[i] - dp[j - a[i]] * prob[i] 表示选择当前物品 i 时的成功概率。这里基于概率的计算原理,假设物品的成功是相互独立事件,使用公式 P(A 或 B) = P(A) + P(B) - P(A) * P(B) 来计算选择当前物品后的成功概率。

通过 max 函数取两者中的最大值更新 dp[j]

代码

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
double dp[N];
double prob[N];
int a[N];
int n,m;
int main(){while(cin>>n>>m){if(n==0 && m==0) break;for(int i=0;i<m;i++){cin>>a[i]>>prob[i];}memset(dp,0,sizeof(dp));for(int i=0;i<m;i++){for(int j=n;j>=a[i];j--){dp[j]=max(dp[j],dp[j-a[i]]+prob[i]-dp[j-a[i]]*prob[i]);}}printf("%.1lf%%\n",dp[n]*100);}return 0;
}

1003

题目

思路

状态转移方程 dp[j]=max(dp[j],dp[j-a[i]]+prob[i]-dp[j-a[i]]*prob[i]);

dp[j] 表示不选择当前物品 i 时,背包容量为 j 的最大成功概率。

dp[j - a[i]] 表示在不放入当前物品 i 时,背包容量为 j - a[i] 的最大成功概率。

dp[j - a[i]] + prob[i] - dp[j - a[i]] * prob[i] 表示选择当前物品 i 时的成功概率。这里基于概率的计算原理,假设物品的成功是相互独立事件,使用公式 P(A 或 B) = P(A) + P(B) - P(A) * P(B) 来计算选择当前物品后的成功概率。

通过 max 函数取两者中的最大值更新 dp[j]

代码

#include<iostream>
using namespace std;
int n,m,l,r,maxnum,sum,temp,num;
int main(){cin>>n;for(int i=0;i<n;i++){l=0,r=0,temp=1,maxnum=-20000,sum=0;cin>>m;for(int j=1;j<=m;j++){cin>>num;sum+=num;if(sum>maxnum){r=j;maxnum=sum;l=temp;}if(sum<0){temp=j+1;sum=0;}}cout<<"Case "<<(i+1)<<":"<<endl<<maxnum<<" "<<l<<" "<<r<<endl;if(i<n-1) cout<<endl;}return 0;
}

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

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

相关文章

一键多环境构建——用 Hvigor 玩转 HarmonyOS Next

引言 在 HarmonyOS Next 的应用开发中&#xff0c;常常需要针对不同环境&#xff08;测试、预发、线上&#xff09;或不同签名&#xff08;调试、正式&#xff09;输出多个 APP/HAP 包。虽然 HarmonyOS 提供了多目标构建&#xff08;Multi-Target Build&#xff09;能力&#…

qt/c++云对象浏览器

简介 本项目为基于QT5和C11的云对象存储可视化管理工具 源码获取 int main(){ printf("源码联系绿泡泡:%s","joyfelic"); return 0; }

【Ubuntu】提升 docker ps -a 输出的可读性:让 Docker 容器状态更清晰

提升 docker ps -a 输出的可读性&#xff1a;让 Docker 容器状态更清晰 当我们使用 docker ps -a 查看所有 Docker 容器时&#xff0c;输出的信息通常会非常多&#xff0c;尤其是在容器数量较多时。默认输出中包含容器 ID、名称、镜像、状态、端口等信息&#xff0c;容易让人眼…

Spring Security自定义身份认证

尽管项目启动时&#xff0c;Spring Security会提供了默认的用户信息&#xff0c;可以快速认证和启动&#xff0c;但大多数应用程序都希望使用自定义的用户认证。对于自定义用户认证&#xff0c;Spring Security提供了多种认证方式&#xff0c;常用的有In-Memory Authentication…

在亚马逊云服务器上部署WordPress服务

在亚马逊云服务器上部署WordPress服务第一步&#xff1a;创建EC2实例第二步&#xff1a;初始设置与安装第三步&#xff1a;配置MySQL与WordPress第四步&#xff1a;配置Apache与WordPress第五步&#xff1a;访问WordPress第六步&#xff1a;测试数据库连接第七步&#xff1a;使…

Web3.0的认知补充(去中心化)

涉及开发技术&#xff1a; Vue Web3.js Solidity 基本认知 Web3.0含义&#xff1a; 新一代互联网思想&#xff1a;去中心化及用户为中心的互联网 数据&#xff1a;可读可写可授权 核心技术&#xff1a;区块链、NFT 应用&#xff1a;互联网上应用 NFT &…

如何修复宝可梦时时刻刻冒险无法正常工作

宝可梦的时时刻刻冒险模式是一项强大的功能&#xff0c;即使应用程序关闭&#xff0c;它也能追踪你的步行距离。它的工作原理是将你的步数与 iOS 上的 Apple Health 或 Android 上的 Google Fit 同步。它对于孵化宝可梦蛋和赚取好友糖果至关重要&#xff0c;但一旦它停止工作&a…

redis常用集合操作命令

在 Redis 的命令行界面&#xff08;redis-cli&#xff09;中&#xff0c; Redis 的集合&#xff08;Set&#xff09;是无序的&#xff0c;且集合中的元素是唯一的。Redis 本身没有直接提供获取集合中某个特定属性的命令&#xff0c;因为集合中的元素是简单的值&#xff0c;而不…

初识数据结构——二叉树从基础概念到实践应用

数据结构专栏 ⬅(click) 初识二叉树&#xff1a;从基础概念到实践应用&#x1f333; 一、树型结构基础 1.1 树的基本概念 树是一种非线性的数据结构&#xff0c;由n(n>0)个有限节点组成一个具有层次关系的集合。它看起来像一棵倒挂的树&#xff0c;根朝上而叶朝下。 关键特…

驼峰命名法(Camel Case)与匈牙利命名法(Hungarian Notation)详解

驼峰命名法&#xff08;Camel Case&#xff09;与匈牙利命名法&#xff08;Hungarian Notation&#xff09;详解及对比‌ ‌1. 驼峰命名法&#xff08;Camel Case&#xff09;‌ ‌定义‌ 驼峰命名法&#xff08;Camel Case&#xff09;是一种变量、函数、类等标识符的命名方…

keil 中优化等级的bug

一&#xff0c;问题描述 程序中代码有的执行&#xff0c;有的不执行&#xff0c;仔细研究&#xff0c;查询人工智能。 程序中printf打印后面的代码不执行&#xff0c; 然后过几十个函数又开始正常了。 二.分析问题 跳过函数一般又判断和Goto等语句&#xff0c;其它的溢出和错误…

织梦dedecms网站如何修改上一篇下一篇的标题字数

一般情况下&#xff0c;如果你的上一篇和下一篇是2行布局就不需要限制标题的字数了&#xff0c;如果你要一行布局上一篇和下一篇标题过长就会打乱网页布局&#xff0c;那么限制上一篇和下一篇的标题字数是需要的&#xff0c;避免页面看起来杂乱不堪。 织梦dedecms网站如何修改…

信创系统 sudoers 权限配置实战!从小白到高手

好文链接&#xff1a;实战&#xff01;银河麒麟 KYSEC 安全中心执行控制高级配置指南 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于信创终端操作系统中 sudoers 文件详解的实用文章&#xff01;在 Linux 系统中&#xff0c;sudo 是一项非常重要的权限控制机制…

《明解C语言入门篇》读书笔记四

目录 第四章&#xff1a;程序的循环控制 第一节&#xff1a;do语句 do语句 复合语句&#xff08;程序块&#xff09;中的声明 读取一定范围内的值 逻辑非运算符 德摩根定律 德摩根定律 求多个整数的和及平均值 复合赋值运算符 后置递增运算符和后置递减运算符 练习…

vite+vue2+elementui构建之 vite.config.js

webpack版本太低&#xff0c;构建依赖太多&#xff0c;头大。 各种查阅资料&#xff0c;弄了一份直通构建vite构建elementUi核心文件&#xff0c; 构建基于开源若依vue2vue3版本改造&#xff0c;感谢开源&#xff0c;感谢若依。 package.json 地址 vitevue2elementui构建之…

超参数详解:从基础概念到优化策略的全面指南

摘要 本文深入解析机器学习中超参数的核心概念&#xff0c;详细对比参数与超参数的本质区别&#xff0c;系统介绍学习率、隐含层数量等常见超参数类型&#xff0c;以及网格搜索、贝叶斯优化等主流寻优方法。结合超参数搜索的标准流程&#xff0c;通过具体案例演示如何高效调整…

计算机视觉与深度学习 | LSTM原理及与卡尔曼滤波的融合

长短期记忆网络(LSTM)是一种特殊的循环神经网络(RNN),旨在解决传统RNN在处理长序列数据时出现的梯度消失和梯度爆炸问题。以下为你详细介绍其基本原理: 核心思想:LSTM的核心思想是引入记忆单元和门控机制来控制信息的流动,从而解决传统RNN的梯度消失问题。记忆单元类似…

EXCEL常用函数公式和VBA汇总第二篇

系列文章目录 文章目录 系列文章目录前言一、excel公式应用1.rand函数2.rand函数随机排序3.rand函数提取数据4.correl函数5.SUBSTITUTE函数6.MAX组合函数7.分析下班时间8.柏拉图自动排序 总结 前言 一、excel公式应用 1.rand函数 用excel生成1-5的随机数字&#xff0c;其中对…

iOS 类与对象底层原理

iOS 类与对象底层原理 文章目录 iOS 类与对象底层原理探索对象本质objc_setProperty 源码cls与类的关联原理联合体isa的类型isa_t 原理探索initIsa方法通过setClass方法中的shiftcls来验证绑定的一个流程通过 isa & ISA_MSAK通过object_getClass通过位运算 类&类的结构…

浮点数:IEEE 754标准

IEEE 754 标准是一种由电气和电子工程师协会&#xff08;IEEE&#xff09;制定的浮点数表示的标准&#xff0c;广泛应用于计算机系统中&#xff0c;下面是详细介绍&#xff1a; 历史背景 在 IEEE 754 标准出现之前&#xff0c;不同的计算机系统采用各自的浮点数表示方法&…