当前位置: 首页 > news >正文

【Luogu】动态规划四

P1095 [NOIP 2007 普及组] 守望者的逃离 - 洛谷

思路:

其实是贪心的dp

一个简单想法是我们可以可以定义dp[i] 为 i 秒内能走过的最大距离,但是由于有魔法限制,我们发现简单的一维是不够的,我们应该还需要一个维度来维护当前魔法

当然我们也可以换一个想法,我们可以直接模拟,用两个人来代表用魔法跑路和走路

如果魔法跑的更快,那么我们最优的选法肯定是选魔法,否则那就走路

模拟过程中我们可以持续更替最大值,同时判断是否能跑出去

至于为什么可以这样,其实也很显然,如果存在一个时间点有 魔法距离 > 光跑步距离,那么此时我们为何不回溯到一开始然后使用魔法策略跑,这显然是更优的

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <utility>
#include <array>
#include <tuple>
using namespace std;
#define int long long
#define yes cout << "Yes" << endl
#define no cout << "No" << endlvoid solve()
{int M, S, T;cin >> M >> S >> T;int lenmagic = 0, lenrun = 0;for (int i = 1; i <= T; i++){if (M >= 10){M -= 10;lenmagic += 60;}else{M += 4;lenrun = max(lenrun, lenmagic);}lenrun += 17;if (max(lenmagic,lenrun) >= S){yes;cout << i;return;}}no;cout << max(lenmagic, lenrun);
}
signed main()
{//cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

P1077 [NOIP 2012 普及组] 摆花 - 洛谷

思路:

题目让我们分配花,最后一定要有m朵

我们定义dp[i][j] 为前 i 种花分配了 j 朵的方法数

那么对于前 i 种花,我们可以枚举 j 的所有可能,同时再对当前的第 i 种枚举这种花选几朵

然后三重循环枚举即可

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <utility>
#include <array>
#include <tuple>
using namespace std;
#define int long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
const int MOD = 1e6 + 7;
int f[105][105];
void solve()
{int n, m;cin >> n >> m;vector<int> a(n+1);for (int i = 1; i <= n; i++){cin >> a[i];}f[0][0] = 1;//枚举前 i 朵花for (int i = 1; i <= n; i++){//枚举选 0 ~ m 种的所有可能for (int j = 0; j <= m; j++){//第 i 种花选 k 朵for (int k = 0; k <= min(j,a[i]); k++){f[i][j] += f[i - 1][j - k];f[i][j] %= MOD;}}}cout << f[n][m];
}
signed main()
{//cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

P2066 机器分配 - 洛谷

思路:

划分dp

我们可以定义 dp[i][j] 为前 i 个公司选了 j 台的最大利润

然后和上题一样三重循环枚举,特别的,由于要字典序最小,所以我们可以倒着枚举

同时储存我们可以定义一个 path[i][j][h] 其代表 对于 前 i 个公司 选了 j 台的方案中 第 h 家公司选了几台

具体转移看代码

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <utility>
#include <array>
#include <tuple>
using namespace std;
#define int long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
int path[11][16][11];
void solve()
{int n, m;cin >> n >> m;vector<vector<int>> mp(n + 1, vector<int>(m + 1, 0));for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){cin >> mp[i][j];}}vector<vector<int>> f(n + 1, vector<int>(m + 1, 0));for (int i = 1; i <= n; i++){//一共选 j 台for (int j = 0; j <= m; j++){//这层选 k 台for (int k = j; k >= 0; k--){if (f[i][j] < f[i - 1][j - k] + mp[i][k]){f[i][j] = f[i - 1][j - k] + mp[i][k];//i j 方案中 第 h 个公司应该分配多少个for (int h = 1; h < i; h++) path[i][j][h] = path[i - 1][j - k][h];path[i][j][i] = k;}}}}cout << f[n][m] << endl;for (int i = 1; i <= n; i++) cout << i << " " << path[n][m][i] << endl;
}
signed main()
{//cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

P2758 编辑距离 - 洛谷

思路:

比较经典的一题

我们可以定义 dp[i][j] 为将 a 的前 i 个字符与 b 的前 j 个字符匹配好需要的最小操作数

那么初始化比较特别,对于所有的 dp[0][j] 有 dp[0][j] = j,同理 dp[i][0] = i,因为是有一个是空的,所以肯定是其长度(全删掉或者全加上)

接下来看转移,显然对于一次转移我们最多只有一次操作,且有以下三种情况

①.从 dp[i-1][j-1] 转移来,此时前 i-1 和 j-1 个字符已经处理完毕,那么只需要在a[i-1]后增加上b[i]即可,特别的,如果 a[i] = b[j],那么就不需要操作

②.从 dp[i-1][j] 转移来,此时 i - 1 与 j 已经匹配完毕,说明 a[i] 是多余的,那么就要执行删除操作

③.从 dp[i][j-1] 转移来,此时 i 与 j - 1 相互匹配,说明 b[j] 还没匹配,那么增加 b[j] 即可

然后最后就是三者取最小值即可

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <utility>
#include <array>
#include <tuple>
using namespace std;
#define int long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endlvoid solve()
{string a, b;cin >> a >> b;int lena = a.length(), lenb = b.length();vector<vector<int>> f(lena + 1, vector<int>(lenb + 1));for (int i = 1; i <= lena; i++){f[i][0] = i;}for (int i = 1; i <= lenb; i++){f[0][i] = i;}a = "#" + a;b = "#" + b;for (int i = 1; i <= lena; i++){for (int j = 1; j <= lenb; j++){if (a[i] == b[j]){f[i][j] = f[i - 1][j - 1];}else{f[i][j] = min(f[i-1][j-1], min(f[i-1][j],f[i][j-1])) + 1;}}}cout << f[lena][lenb];
}
signed main()
{//cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

相关文章:

  • 2025时间序列都有哪些创新点可做——总结篇
  • 常用第三方库:flutter_boost混合开发
  • Shell脚本-while循环语法结构
  • MySQL数据库(13) 用户管理
  • kubernetes环境手动部署 Prometheus 监控系统安装文档
  • 差分优化效率
  • 研发内控新规下的合规之道:维拉工时助力企业穿越IPO审查雷区
  • 深入浅出 MVVM:理解现代前端开发的核心架构模式
  • 贪心算法~~
  • Sand AI 开源 MAGI-1 视频生成模型,近屿智能带你领略无限扩展的 AI 视界
  • 《深入理解计算机系统》阅读笔记之第二章 信息的表示和处理
  • Apipost免费版、企业版和私有化部署详解
  • 保安员证考试的理论知识有哪些重点?
  • 计算机基础 原码反码补码问题
  • 一篇速成Linux 设置位 S(SetUID)
  • kafka课后总结
  • 简述:变更调查的历史情况
  • 定时任务:Quartz
  • Windows同步技术-使用命名对象
  • MySQL引擎分类与选择、SQL更新底层实现、分库分表、读写分离、主从复制 - 面试实战
  • 幸福航空取消“五一”前航班,财务人员透露“没钱飞了”
  • 黄永年:说狄仁杰的奏毁淫祠
  • 第二十届华表奖提名名单公布,张译、王一博、马丽、郭帆等入围
  • 涉李小龙形象商标被判定无效,真功夫:暂无更换计划
  • 新城市志|中国消费第一城,迎来“补贴力度最大”购物节
  • 魔都眼·上海车展⑤|被主播包围的新车