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

【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;
}

http://www.xdnf.cn/news/1926.html

相关文章:

  • Hot100方法及易错点总结2
  • firewalld 详解
  • 微信小程序蓝牙连接打印机打印单据完整Demo【蓝牙小票打印】
  • 【prompt是什么?有哪些技巧?】
  • Linux操作系统复习
  • 3D模型文件格式之《STL格式介绍》
  • SSH服务介绍
  • string的基本使用
  • uniapp自定义封装tabbar
  • 探索亚马逊云科技:开启您的云计算之旅
  • Safety Estimands与Efficacy Estimands的差异剖析
  • 模式设计简介
  • 北斗导航 | 北斗卫星导航单点定位精度提升方法总结,原理,公式,关键代码
  • 架构师面试(三十六):广播消息
  • websheet 之 sheet操作
  • c++11新特性随笔
  • 使用开源免费雷池WAF防火墙,接入保护你的网站
  • Shell 脚本入门:从零开始写自动化脚本
  • 代码随想录算法训练营day11(二叉树)
  • 轻量级静态网站托管:服务器配置与网站性能深入探讨
  • Sui 携手 xMoney 和 xPortal 推出虚拟万事达卡,拓展现实支付场景接入
  • 分布式ID生成方案详解
  • 软件为什么需要性能测试?软件测试机构性能测试注意事项有哪些?
  • 实时数据驱动未来:谷云科技CDC实时数据集成平台新版本发布
  • JAVA常用分布式锁Redisson
  • 大模型驱动智能服务变革:从全流程赋能到行业纵深落地
  • WHAT - 前端开发书单推荐
  • 带宽?增益带宽积?压摆率?
  • 基于物联网的智能家居安全防护系统设计
  • Java 24 深度解析:云原生时代的性能更新与安全重构