第18节 动态规划一讲

1假设有排成一行的N个位置记为1~N,N一定大于或等于2
开始时机器人在其中的M位置上(M一定是1~N中的一个)
如果机器人来到1位置,那么下一步只能往右来到2位置;
如果机器人来到N位置,那么下一步只能往左来到N-1位置;
如果机器人来到中间位置,那么下一步可以往左走或者往右走;
规定机器人必须走K步,最终能来到P位置(P也是1~N中的一个)的方法有多少种
给定四个参数 N、M、K、P,返回方法数

动态规划:如果在调用过程中有重复调用过程就将他存起来

比如递归求斐波那契数列,中间有不少重复过程

 递归策略:

#include <vector>using namespace std;class Solution {
public:int ways1(int N, int start, int aim, int K) {if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) {return -1;}return process1(start, K, aim, N);}
/ 机器人当前来到的位置是cur,// 机器人还有rest步需要去走,// 最终的目标是aim,// 有哪些位置?1~N// 返回:机器人从cur出发,走过rest步之后,最终停在aim的方法数,是多少?private:int process1(int cur, int rest, int aim, int N) {if (rest == 0) {return cur == aim ? 1 : 0;}if (cur == 1) {return process1(2, rest - 1, aim, N);}if (cur == N) {return process1(N - 1, rest - 1, aim, N);}return process1(cur - 1, rest - 1, aim, N) + process1(cur + 1, rest - 1, aim, N);}
};

这个递归来进行优化

该递归中出现了重复解

cur范围1到n

rest范围0到k

准备一张dp表,先全设为-1,表示没算过这个过程

#include <vector>using namespace std;class Solution {
public:int ways2(int N, int start, int aim, int K) {if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) {return -1;}vector<vector<int>> dp(N + 1, vector<int>(K + 1, -1));return process2(start, K, aim, N, dp);}private:int process2(int cur, int rest, int aim, int N, vector<vector<int>>& dp) {if (dp[cur][rest] != -1) {return dp[cur][rest];}//算过的值就塞入缓存表int ans = 0;if (rest == 0) {ans = cur == aim ? 1 : 0;}else if (cur == 1) {ans = process2(2, rest - 1, aim, N, dp);}else if (cur == N) {ans = process2(N - 1, rest - 1, aim, N, dp);}else {ans = process2(cur - 1, rest - 1, aim, N, dp) + process2(cur + 1, rest - 1, aim, N, dp);}dp[cur][rest] = ans;//没算过的算出来了也塞入缓存表return ans;}
};

 再往下优化,直接填这张动态规划表

 

不要硬憋状态转移,要去想尝试策略

#include <vector>using namespace std;class Solution {
public:int ways3(int N, int start, int aim, int K) {if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) {return -1;}vector<vector<int>> dp(N + 1, vector<int>(K + 1, 0));dp[aim][0] = 1;for (int rest = 1; rest <= K; rest++) {dp[1][rest] = dp[2][rest - 1];for (int cur = 2; cur < N; cur++) {dp[cur][rest] = dp[cur - 1][rest - 1] + dp[cur + 1][rest - 1];}dp[N][rest] = dp[N - 1][rest - 1];}return dp[start][K];}
};

 2给定一个整型数组arr,代表数值不同的纸牌排成一条线
玩家A和玩家B依次拿走每张纸牌
规定玩家A先拿,玩家B后拿
但是每个玩家每次只能拿走最左或最右的纸牌
玩家A和玩家B都绝顶聪明
请返回最后获胜者的分数

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int f1(vector<int>& arr, int L, int R);
int g1(vector<int>& arr, int L, int R);int win1(vector<int>& arr) {if (arr.empty()) {return 0;}int first = f1(arr, 0, arr.size() - 1);int second = g1(arr, 0, arr.size() - 1);return max(first, second);
}int f1(vector<int>& arr, int L, int R) {if (L == R) {return arr[L];}int p1 = arr[L] + g1(arr, L + 1, R);int p2 = arr[R] + g1(arr, L, R - 1);return max(p1, p2);
}int g1(vector<int>& arr, int L, int R) {if (L == R) {return 0;}int p1 = f1(arr, L + 1, R); // 对手拿走了L位置的数int p2 = f1(arr, L, R - 1); // 对手拿走了R位置的数return min(p1, p2);
}int main() {vector<int> arr = {3, 9, 1, 2};cout << win1(arr) << endl; // 示例输入,输出结果根据实际情况可能不同return 0;
}

 弄两张表进行记忆化缓存

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int f2(vector<int>& arr, int L, int R, vector<vector<int>>& fmap, vector<vector<int>>& gmap);
int g2(vector<int>& arr, int L, int R, vector<vector<int>>& fmap, vector<vector<int>>& gmap);int win2(vector<int>& arr) {if (arr.empty()) {return 0;}int N = arr.size();vector<vector<int>> fmap(N, vector<int>(N, -1));vector<vector<int>> gmap(N, vector<int>(N, -1));int first = f2(arr, 0, arr.size() - 1, fmap, gmap);int second = g2(arr, 0, arr.size() - 1, fmap, gmap);return max(first, second);
}int f2(vector<int>& arr, int L, int R, vector<vector<int>>& fmap, vector<vector<int>>& gmap) {if (fmap[L][R] != -1) {return fmap[L][R];}int ans = 0;if (L == R) {ans = arr[L];} else {int p1 = arr[L] + g2(arr, L + 1, R, fmap, gmap);int p2 = arr[R] + g2(arr, L, R - 1, fmap, gmap);ans = max(p1, p2);}fmap[L][R] = ans;return ans;
}int g2(vector<int>& arr, int L, int R, vector<vector<int>>& fmap, vector<vector<int>>& gmap) {if (gmap[L][R] != -1) {return gmap[L][R];}int ans = 0;if (L != R) {int p1 = f2(arr, L + 1, R, fmap, gmap); // 对手拿走了L位置的数int p2 = f2(arr, L, R - 1, fmap, gmap); // 对手拿走了R位置的数ans = min(p1, p2);}gmap[L][R] = ans;return ans;
}int main() {vector<int> arr = {3, 9, 1, 2};cout << win2(arr) << endl; // 示例输入,输出结果根据实际情况可能不同return 0;
}

 

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int win3(vector<int>& arr) {if (arr.empty()) {return 0;}int N = arr.size();vector<vector<int>> fmap(N, vector<int>(N));vector<vector<int>> gmap(N, vector<int>(N));for (int i = 0; i < N; i++) {fmap[i][i] = arr[i];}for (int startCol = 1; startCol < N; startCol++) {int L = 0;int R = startCol;while (R < N) {fmap[L][R] = max(arr[L] + gmap[L + 1][R], arr[R] + gmap[L][R - 1]);gmap[L][R] = min(fmap[L + 1][R], fmap[L][R - 1]);L++;R++;}}return max(fmap[0][N - 1], gmap[0][N - 1]);
}int main() {vector<int> arr = {3, 9, 1, 2};cout << win3(arr) << endl; // 示例输入,输出结果根据实际情况可能不同return 0;
}

 

 

 

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

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

相关文章

【LeetCode: 2684. 矩阵中移动的最大次数 + dfs】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

数据结构的概念大合集04(队列)

概念大合集04 1、队列1.1 队列的定义1.2队列的顺序存储1.2.1 顺序队1.2.2 顺序队的基本运算的基本思想1.2.3 顺序队的4要素的基本思想 1.3 环形队列1.3.1 环形队列的定义1.3.1 环形队列的实现 1.4 队列的链式存储1.4.1 链队1.4.2 链队的实现方式1.4.3 链队的4要素的基本思想 1.…

牛客网-SQL大厂面试题-1.各个视频的平均完播率

题目&#xff1a;各个视频的平均完播率 DROP TABLE IF EXISTS tb_user_video_log, tb_video_info; CREATE TABLE tb_user_video_log (id INT PRIMARY KEY AUTO_INCREMENT COMMENT 自增ID,uid INT NOT NULL COMMENT 用户ID,video_id INT NOT NULL COMMENT 视频ID,start_time dat…

智慧交通:构建智慧城市的重要一环

随着信息技术的飞速发展&#xff0c;智慧城市已成为现代城市发展的重要方向。作为智慧城市的重要组成部分&#xff0c;智慧交通以其高效、便捷、环保的特性&#xff0c;成为推动城市现代化进程的关键力量。本文将从智慧交通的概念、发展现状、面临挑战以及未来趋势等方面&#…

SQLiteC/C++接口详细介绍之sqlite3类(十五)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十四&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十六&#xff09; 47.sqlite3_set_authorizer 用法&#xff…

快慢指针:妙解查找链表的中间结点问题

给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个中间结点&#xff0c;值为 3 。示…

HarmonyOS NEXT应用开发—Grid和List内拖拽交换子组件位置

介绍 本示例分别通过onItemDrop()和onDrop()回调&#xff0c;实现子组件在Grid和List中的子组件位置交换。 效果图预览 使用说明&#xff1a; 拖拽Grid中子组件&#xff0c;到目标Grid子组件位置&#xff0c;进行两者位置互换。拖拽List中子组件&#xff0c;到目标List子组件…

深入浅出 Spring:核心概念和基本用法详解

个人主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1b;《Java》 一、引言 在 Java 企业级应用开发中&#xff0c;Spring 框架已经成为了事实上的标准。它提供了一种轻量级的解决方案&#xff0c;使得开发者能够更轻松地构建灵活、可扩展的应用程序。在本文中&#xff0c…

如何保存缓存和MySQL的双写一致呢?

如何保存缓存和MySQL的双写一致呢&#xff1f; 所谓的双写一致指的是&#xff0c;在同时使用缓存(如Redis)和数据库(如MySQL)的场景下,确保数据在缓存和数据库中的更新操作保持一致。当对数据进行修改的时候&#xff0c;无论是先修改缓存还是先修改数据库&#xff0c;最终都要保…

Flink 集群部署模式

文章目录 前言一、会话模式&#xff08;Session Mode&#xff09;二、单作业模式&#xff08;Per-Job Mode&#xff09;三、应用模式&#xff08;Application Mode&#xff09; 前言 Flink支持多种集群部署模式&#xff0c;以满足不同场景和需求。以下是Flink的主要集群部署模…

【数据结构取经之路】希尔排序

目录 引言 思想 动图 过程展开图 gap的取值 时间复杂度 空间复杂度 代码及其解释 引言 希尔排序(Shells Sort)是插入排序的一种又称“缩小增量排序”&#xff08;Diminishing Increment Sort&#xff09;&#xff0c;是直接插入排序算法的一种更高效的改进版本。希尔排…

基于GT911触控IC的电容屏在MSP430上的驱动

背景 最近参加公司一个电池测试仪的项目&#xff0c;负责电容屏驱动开发&#xff0c;电容屏的触控IC是汇顶科技的GT911&#xff0c;电容屏的总线接口是I2C。 因为项目沟通方面的失误&#xff0c;本应接到主控芯片的电容屏&#xff0c;被连到了MSP430这款负责供电管理的MCU&…