当前位置: 首页 > 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;
}


http://www.mrgr.cn/news/100092.html

相关文章:

  • Operating System 实验二 内存管理实验
  • cdh平台管理与运维最佳实践
  • 联合体和枚举类型
  • 游戏引擎学习第244天: 完成异步纹理下载
  • 附赠二张图,阐述我对大模型的生态发展、技术架构认识。
  • PR第二课--混剪
  • 巧记英语四级单词 Unit5-中【晓艳老师版】
  • java配置
  • string的基本使用
  • 【初识Trae】字节跳动推出的下一代AI原生IDE,重新定义智能编程
  • 图像预处理-图像亮度变换
  • 查找函数【C++】
  • 二项式分布html实验
  • Linux学习笔记之环境变量
  • 全栈开发的未来:低代码与AI辅助编程的边界探索
  • Linux网络编程 原始套接字与ARP协议深度解析——从数据包构造到欺骗攻防
  • 【linux】Chrony服务器
  • 区间和数量统计 之 前缀和+哈希表
  • AI 开发工具提示词集体开源!解锁 Cursor、Cline、Windsurf 等工具的核心逻辑
  • SpringBoot 学习