【算法解题思想】动态规划+深度优先搜索(C/C++)

简介: 【算法解题思想】动态规划+深度优先搜索(C/C++)

动态规划

动态规划(Dynamic Programming,简称 DP)是一种在数学、管理科学、计算机科学和经济学中用于求解决策过程最优化的数学方法。它通过将复杂问题分解成简单的子问题来解决,通过保存子问题的解,避免重复计算,从而提高效率。

动态规划通常适用于具有以下特点的问题:

  1. 最优子结构:动态规划每一步的最优,局部最优解。
  2. 重叠子问题:一个问题分解成多个子问题,这些问题会有重复的问题。
  3. 无后效性:一个状态的值被状态转移方程计算出来,那么它就是不可以变化的,后面的状态可以把他拿过来用。

动态规划的基本步骤包括:

  1. 定义状态:求解动态规划,先要定义dp数组,其意义是什么。
  2. 建立状态转移方程:根据问题的特点,以及联系性,对状态建立状态转移方程。
  3. 确定初始状态和边界条件:确定了状态转移方程,那么就要确定初始条件、值,保证状态转移方程的计算。
  4. 计算状态:按照状态转移方程计算每一个状态。
  5. 得到解:根据计算的状态,以及题目所问的是什么进行输出应该的答案。

动态规划的应用非常广泛,包括但不限于:

  • 最短路径问题:如Dijkstra 算法和 Floyd-Warshall 算法。
  • 背包问题:包括 0/1 背包问题和树形背包等等。
  • 最长公共子序列:求解两个序列的最长公共子序列。
  • 最大子矩阵:求解二维数组中最大的子矩阵的值。 image.gif

动态规划的实现方法通常有两种:

  1. 自顶向下的递归方法:使用递归公式从一般到特殊解决问题,通常需要配合记忆化来避免重复计算,又称记忆化搜索。
  2. 自底向上的迭代方法:从最简单的子问题开始,逐步构建复杂问题的解。

深度优先搜索

算法介绍:

深度优先搜索(Depth-First Search,简称DFS)是一种用于遍历或搜索树或图的算法。这种算法会尽可能深地搜索图的分支,直到找到目标节点或达到叶节点(没有子节点的节点),然后回溯到上一个分支继续搜索。DFS可以用于许多问题,比如路径寻找、连通性验证、拓扑排序等。


基本步骤:

DFS通常使用递归或栈来实现。以下是DFS的基本步骤

选择起始点:选择图中的一个点作为起始点。

访问节点:标记起始节点为已访问,并将该节点加入递归或栈中。

探索邻接节点:从该点周围取出一个点,检查它的所有未访问的邻接节点。

递归或迭代:对每个未访问的邻接节点,将其标记为已访问,然后将其推入递归或栈中。

回溯:当当前节点的所有邻接节点都被访问后,递归中回溯/从栈中弹出该节点,继续搜索上一个点的其他分支。

结束条件:当栈为空或找到目标节点时,搜索结束。

题目描述

给定一个信封,最多只允许粘贴 N 张邮票,计算在给定 K(N+K≤15)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值 MAX,使在 1 至 MAX 之间的每一个邮资值都能得到。

例如,N=3,K=2,如果面值分别为 1 分、4 分,则在 1∼6 分之间的每一个邮资值都能得到(当然还有 8 分、9 分和 12 分);如果面值分别为 1 分、3 分,则在 1∼7 分之间的每一个邮资值都能得到。可以验证当 N=3,K=2 时,7 分就是可以得到的连续的邮资最大值,MAX=7,面值分别为 1 分、3 分。

输入格式

2 个整数,代表 N,K。

输出格式

输出共 2 行。

第一行输出若干个数字,表示选择的面值,从小到大排序。

第二行,输出 MAX=S, 表示最大的面值。

输入输出样例

输入 #1

3 2


输出 #1

1 3

MAX=7


解题思路:

此题主要利用了dp+dfs,根据题目来看需要k种邮票,那么需要哪几种邮票,这就需要枚举,dfs去每一步搜索,题目中要求最大连续长度,考虑dp去解决,要求最大连续长度,意思就是通过这k种面值,能够连续不间断组成1~?之间的每一个数,那么我定义一个f[M]表示通过k种面值得到分值为M的最少邮票张数,只要这个值小于题目中给定的邮票张数n,那么从小到达遍历,此位置前面的都是连续的,当找到第一个不满足<n的分数i时,那么它前面i-1都是连续的,即此方案的最大连续长度为i-1,如果找不到这样的条件,那么能组成的值都是小于n的,最大连续长度就是最大的邮票值*n。


那么我们重新顺一下解题思路,首先枚举这k种邮票面值组合,我们解决办法是最简单的dfs,我们枚举出这k种面值组合,对它进行求解最大连续长度,处理办法是dp,具体解释注释在代码上。


代码实现:

#include<iostream>
#include<cstring>
using namespace std;
const int N=20;
const int inf=0x3f3f3f;
int n,k,res;//res保存答案
int a[N],ans[N],f[50000];//f[i]拼面值为i所需要最小张数
//a[i]组成的分数中间过渡数组,ans[i]满足条件的答案分数数组
int dp(int t,int mx){
  f[0]=0;//初始化特例
  for(int i=1;i<=a[t]*n;i++)f[i]=inf;//初始化正无穷
  for(int i=1;i<=k;i++){//k种位数
    for(int j=a[i];j<=a[t]*n;j++){//最大连续长度至少以自己分数为起始,最大到填满n张最大的面值a[t]
      f[j]=min(f[j],f[j-a[i]]+1); //类似于背包更新
    }
  }
  for(int i=1;i<=a[t]*n;i++){
    if(f[i]>n){//若此时填的面值张数大于邮票可以贴的最大张数,就说明此时i不满足,前i-1是满足的
      return i-1;
    }
  }
  return a[t]*n;//若前面都成立那么最大连续分数就是最大值分数*张数
} 
void dfs(int dep,int x){//dep种分数组成x为连续最大长度 
  if(dep==k+1){//当分数种数为k种,满足条件
    if(x>res){//此时最大连续长度大于res满足更新条件
      res=x;//更新
      for(int i=1;i<=k;i++){
        ans[i]=a[i];
      }
    }
    return;
  }
  for(int i=a[dep-1]+1;i<=x+1;i++){//为了不避免重复,至少是上一位的分数值+1,最大到x+1,否则前面的也会不连续
    a[dep]=i;
    int t=dp(dep,x);//t更新最大连续长度
    dfs(dep+1,t);
  }
}
int main(){
  cin>>n>>k;
  dfs(1,0);//从1开始去找,第一个分必是1,初始最大长度为0
  for(int i=1;i<=k;i++)
      cout<<ans[i]<<" ";
    cout<<endl;
    cout<<"MAX="<<res<<endl;
  return 0;
}

题后总结:

此题博主感觉难度较大,如果题量够大,可能对他们来说,一眼就出思路,dfs+dp这种题第一次做,当时看的是罗老师的B站讲解,大家看不懂的可以去看看。

信奥编程罗老师:P1021 [NOIP1999 提高组] 邮票面值设计_哔哩哔哩_bilibili

:图片来自罗老师讲解。

相关文章
|
2月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
72 1
|
3月前
|
人工智能 运维 算法
基于 C# 深度优先搜索算法的局域网集中管理软件技术剖析
现代化办公环境中,局域网集中管理软件是保障企业网络高效运行、实现资源合理分配以及强化信息安全管控的核心工具。此类软件需应对复杂的网络拓扑结构、海量的设备信息及多样化的用户操作,而数据结构与算法正是支撑其强大功能的基石。本文将深入剖析深度优先搜索(Depth-First Search,DFS)算法,并结合 C# 语言特性,详细阐述其在局域网集中管理软件中的应用与实现。
84 3
|
4月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
117 15
|
4月前
|
监控 算法 安全
基于 PHP 语言深度优先搜索算法的局域网网络监控软件研究
在当下数字化时代,局域网作为企业与机构内部信息交互的核心载体,其稳定性与安全性备受关注。局域网网络监控软件随之兴起,成为保障网络正常运转的关键工具。此类软件的高效运行依托于多种数据结构与算法,本文将聚焦深度优先搜索(DFS)算法,探究其在局域网网络监控软件中的应用,并借助 PHP 语言代码示例予以详细阐释。
81 1
|
4月前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
5月前
|
运维 监控 JavaScript
内网网管软件中基于 Node.js 的深度优先搜索算法剖析
内网网管软件在企业网络中不可或缺,涵盖设备管理、流量监控和安全防护。本文基于Node.js实现深度优先搜索(DFS)算法,解析其在网络拓扑遍历中的应用。通过DFS,可高效获取内网设备连接关系,助力故障排查与网络规划。代码示例展示了图结构的构建及DFS的具体实现,为内网管理提供技术支持。
84 11
|
2月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
87 17
|
5月前
|
机器学习/深度学习 算法
算法系列之搜索算法-深度优先搜索DFS
深度优先搜索和广度优先搜索一样,都是对图进行搜索的算法,目的也都是从起点开始搜索,直到到达顶点。深度优先搜索会沿着一条路径不断的往下搜索,直到不能够在继续为止,然后在折返,开始搜索下一条候补路径。
224 62
算法系列之搜索算法-深度优先搜索DFS
|
1月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
36 0
|
4月前
|
算法 安全 Java
算法系列之深度优先搜索寻找妖怪和尚过河问题的所有方式
在算法学习中,深度优先搜索(DFS)是一种常用的图搜索算法,通过递归或栈实现,适合路径搜索、连通性、拓扑排序、回溯、生成、环路检测、强连通分量和可达性等问题。本文将介绍如何利用深度优先搜索解决“妖怪和尚过河问题”的所有方式。
117 26
算法系列之深度优先搜索寻找妖怪和尚过河问题的所有方式