动态规划(DP)经典模型
1,动态规划(DP) 记忆化搜索 实质上是以空间换时间
最优子结构
无后效性
子问题重叠性 ---> 记忆化搜索
2,dp思想
开个数组存
计算前先看计算过没,计算过了直接返回结果
3,记忆化搜索 求解斐波纳契数列
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
int dp[maxn];
// 记忆化搜索的基本结构
// 要怎么表示没被算过?
int f (int x)
{// 算过了就不算了, 记忆化搜索的关键,一定要放在dfs的开头!!!!if (dp[x] != -1) return dp[x];if (x == 1 || x == 2) return 1;int ans = f(x - 1) + f(x - 2);dp[x] = ans;return ans;
}
int main()
{int n; cin >> n;// 把所有dp置为-1// memset 不是什么值都可以赋的!// 只能初始化0 || -1memset(dp , -1 , sizeof dp);cout << f(n) << endl;return 0;
}
memset,只能初始化0或者-1,fill初始化
memset(dp,-1/0,sizeof dp);
fill (array,array+4,5); // myvector: 5 5 5 5 0 0 0 0
fill (array+3,array+6,8); // myvector: 5 5 5 8 8 8 0 0
3,数塔模型 记忆化搜索
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int inf = 1e9;
int dp[maxn][maxn] , a[maxn][maxn];
int n , m;
// dfs的作用:求从x,y到底部的路径最大值
int dfs (int x , int y)
{// 边界条件// 不合法的状态,我们要让他一定不被考虑。// 如果全部都是负数,那么返回0将是错误的结果if (y > x) return -inf;if (dp[x][y] != -1) return dp[x][y];if (x == n + 1) return 0;int ans = a[x][y] + max (dfs(x + 1 , y) , dfs(x + 1 , y + 1));dp[x][y] = ans;return ans;
}
int main()
{// 把所有dp置为-1// memset 不是什么值都可以赋的!// 只能初始化0 || -1memset(dp , -1 , sizeof dp);cin >> n >> m;for (int i = 1 ; i <= n; i ++){for (int j = 1 ; j <= i ; j++){cin >> a[i][j];}}cout << dfs(1 , 1) << endl;return 0;
}
4,数塔问题 递推解法
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int inf = 1e9;
// dp(x , y) 从(x , y)到最下面一层的最大值
int dp[maxn][maxn] , a[maxn][maxn];
int main()
{int t; cin >> t;while (t--){// 初始化memset (dp , 0 , sizeof dp);int n; cin >> n;for (int i = 1 ; i <= n ; i++){for (int j = 1 ; j <= i ; j++){cin >> a[i][j];}}for (int i = n ; i >= 1 ; i--){for (int j = 1 ; j <= i ; j++){dp[i][j] = a[i][j] + max(dp[i + 1][j] , dp[i + 1][j + 1]);}}cout << dp[1][1] << endl;}return 0;
}
4,最大子段和 一段数最大的和 aL-aR
b[i]以i结尾最大的的子段和
max(a[i]+b[i],a[i]); +b[i]<a[i] 就不用接了
求具体方案
从c[i] (以i为结尾的最大子段和的起始点) 不接 起点是c[i]-1 接 起点是从c[i];
5,序列组合
n个格子,每个格子可填写数[1,m].满足任意一对相邻的格子的数绝对值小于等于2的填写方案数
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int inf = 1e9;
int n , m;
// dfs (st , val) 求从st填写到1格子的所有可能方案.
int dp[105][108];
int dfs (int st , int val)
{if (dp[st][val] != -1) return dp[st][val];if (st == 0) return 1;int ans = 0;for (int i = 1 ; i <= m ; i++){if (abs(val - i) <= 2){ans += dfs(st - 1 , i);}}dp[st][val] = ans;return ans;
}
int main()
{memset(dp , -1 , sizeof dp);cin >> n >> m;int ans = 0;for (int i = 1 ; i <= m ; i++){ans += dfs (n - 1 , i);}cout << ans << endl;return 0;
}
递推版本
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int inf = 1e9;
int n , m;
// dp(i , j) 代表从1号格子填写到第i号格子,且第i号格子的数为j的所有方案数.
int dp[maxn][maxn];
int main()
{memset(dp , -1 , sizeof dp);int n , m; cin >> n >> m;// 边界条件,因为1之前没有格子了for (int i = 1 ; i <= m ; i++)dp[1][i] = 1;// 从2开始转移.for (int i = 2 ; i <= n ; i++){for (int j = 1 ; j <= m ; j++){for (int k = max(j - 2 , 1) ; k <= min(j + 2 , m) ; k++){dp[i][j] += dp[i - 1][k];}}}int ans = 0;for (int i = 1 ; i <= m ; i++){ans += dp[n][i];}cout << ans << endl;return 0;
}
6,LIS(最长上升子序列)
O(n^2)
dp[i]=max(a[j]+1); dp[j]<dp[i]
#include <iostream>using namespace std;
int a[105],dp[105];
int main()
{int n;cin>>n;fill(dp,dp+n,1);//初始化数组为1for(int i=1;i<=n;i++){cin>>a[i];}//dp[1]=1;for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){if(a[i]>a[j]){dp[i]=max(dp[i],dp[j]+1);}}}for(int i=1;i<=n;i++){cout<<dp[i]<<" ";}return 0;
}
7,走格子
8最长公共子序列
dp[i][j]是第一个字符串的前i个字符与第二个字符串前j个字符的最长公共子序列的长度
x==y dp[i][j]=dp[i-1][j-1]+1
x!=y dp[i][j]=max(dp[i-1][j] dp[i][j-1])
8,回文串模型
给你一个字符串长度为2000 Q(Q<=1e6)次询问 [L,R]子串是否为回文串
dp[L][R]=dp[L+1][R-1]&&s[L]==s[R];
dp[i][j]表示区间L-R是否为回文串
#include <bits/stdc++.h>using namespace std;
int dp[2000][2000];
int main()
{string str;cin>>str;str='#'+str;for(int i=str.size();i>0;i--){for(int j=i;j<=str.size();j++){//i-j==0 "a"//i-j==1 "aa"//i-j==2 "aba"//前提是str[i]==str[j]dp[i][j]=(str[i]==str[j])&&(i-j<=2||dp[i+1][j-1]);}}int q;cin>>q;while(q--){int x,y;cin>>x>>y;if(dp[x][y]){cout<<"yes"<<endl;}else{cout<<"no"<<endl;}}return 0;
}
/*-------------------------------*/
求最长回文子序列
dp[i][j] i表示头 j表示尾 头尾最长的回文子序列
s[i]==s[j] dp[i][j]=dp[i+1][j-1]+1
s[i]!=s[j] dp[i][j]=max(dp[i+1][j],dp[i][j-1])
#include<bits/stdc++.h>
using namespace std;
int dp[1300][1300];
int main(){string s;cin>>s;int n=s.size();for(int i=0;i<n;i++){if(s[i]>='A'&&s[i]<='Z'){s[i]=s[i]+32;}}s="*"+s;memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){for(int j=n;j>=1;j--){if(s[i]==s[j]){dp[i][j]=dp[i-1][j+1]+1;}else{dp[i][j]=max(dp[i-1][j],dp[i][j+1]);}}}cout<<dp[n][1]<<endl;return 0;
}
9,背包模型
n个物品 体积v,价值w(n,m<1000,w<=1e9)
取n个物品(不超过体积的前提下)使价值最大
dfs(st,v)
max(dfs(st+1,v) w[st]+dfs(st+1,v-v[st]);
动态规划(DP)经典模型相关推荐
- 算法讲解 -- 区间dp经典模型与优化(石子归并)
石子合并问题是最经典的DP问题.首先它有如下3种题型: PPT讲解:点击打开链接 (1)有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为新合成的一堆石子的数 ...
- 动态规划DP经典题目Java版本
动态规划经典题目汇总(多点赞关注哦) (1)最长公共子序列: package 动态规划;import java.util.Scanner;/*** abcdebcde4* @author Admini ...
- 动态规划27k字超详细保姆级入门讲解——附DP经典线性、区间、二维图、四维8个模型题解
动态规划27k字超详细保姆级入门讲解 写在前面: 这篇文章是目前为止我写过最长也是最久的文章,前面关于DP的讲解我查阅了大量的博客资料,学习其他博主对DP的理解,也翻阅了很多经典的纸质书籍,同时做了近 ...
- [刷题记录] luogu网络流24题 及 网络流心得体会 及 经典模型不定期更新
文章目录 信息汇总表格 飞行员配对方案问题 分配问题 运输问题 数字梯形问题 最小路径覆盖问题 魔术球问题 圆桌问题 试题库问题 深海机器人问题 航空路线问题 火星探险问题 太空飞行计划问题 方格取数 ...
- 动态规划之经典的鸡蛋坠楼问题详解
开篇 经过了各种惨痛的公司笔试失利之后,慢慢掌握了公司出题的一些套路,其中动态规划是避免不了的.最近研究了一些公司笔试的一些出题思路和套路,加上自己看的一些大神的面经,打算写一些关于公司常见笔试类型题 ...
- 动态规划:经典题目汇总
动态规划:经典题目汇总 文章目录 动态规划:经典题目汇总 一.动态规划的定义 二.经典例题 3.1 一维的DP:斐波那契数列.[使用最小花费爬楼梯](https://leetcode-cn.com/p ...
- PyTorch Hub发布获Yann LeCun强推!一行代码调用经典模型
作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 导读:6月11日,Facebook PyTorch 团队推出了全 ...
- 分组卷积新进展,全自动学习的分组有哪些经典模型?
作者&编辑 | 言有三 1 CondenseNet CondenseNet 以前我们给大家讲了许多的分组网络,如果分组本身可以学习,而不是通过预先定义的规则,可能取得更好的效果,其中的一个典型 ...
- 点击率预估的几个经典模型简介
点击率预估的几个经典模型简介 2016-02-22 00:32 点击率预估是大数据技术应用的最经典问题之一,在计算广告,推荐系统,金融征信等等很多领域拥有广泛的应用.本文不打算对这个话题做个全面 ...
- AI开发者大会之AI学习与进阶实践:2020年7月3日《如何转型搞AI?》、《基于AI行业价值的AI学习与进阶路径》、《自动机器学习与前沿AI开源项目》、《使用TensorFlow实现经典模型》
AI开发者大会之AI学习与进阶实践:2020年7月3日<如何转型搞AI?>+<无行业不智能:基于AI行业价值的AI学习与进阶路径>.<自动机器学习与前沿AI开源项目> ...
最新文章
- 聊聊flink的InternalTimeServiceManager
- 未来软件是什么样呢?数据库篇(转载)
- PaperNotes(12)-Autoregressive Quantile networks for generative modeling
- http代理的脚本http_proxy.py
- 阿里道延:我对技术架构的理解与架构师角色的思考
- 每日小记 2017 2.9
- c++中4个与类型转换相关的关键字总结
- [Android Pro] java.lang.IllegalStateException: Fragment(XXFragment) not attached to Activity异常
- jQuery实现一个简单的选项卡效果
- kali linux 自动登录,Kali Linux SSH登录故障处理
- 日常工具搬运——python逐行写入txt文件
- 第四届组织医学与再生医学国际学术研讨会(CTERM-BT 2019)
- 估值3000亿,中国最神秘电商公司,征服美国年轻人
- OSChina 周六乱弹 —— 我都想和他们组成一个家庭了
- ICP-MS和ICP-AES的区别与检出限
- Python用socket、多线程实现一对一聊天室
- Mysql索引结构全维度比较
- VSCode_快捷键
- 喇叭音箱的频率范围和频率响应
- Charles最新破解版苹果iphone安卓android手机抓包分析教程笔记
热门文章
- 罗比机器人说明书_罗比_机器人人物_我要机器人
- 广告策划书的一般模式
- 带你快速看完9.8分神作《Effective Java》—— 并发篇(工作里的这些坑你都遇到过吗?)
- html如何实现文字跳动,JS代码怎么实现文字跳动特效?
- oracle条件索引查询,Oracle复合索引用于范围查询条件
- phpnow怎么改php版本,phpnow升级php版本的方法
- 39 What Determines the Kind of Person You Are ?是什么决定了你是哪种内型的人 ?
- linux 目录历史于特点,linux 返回上次历史目录
- 希捷硬盘无法连接计算机,新买的希捷1T移动硬盘在电脑上没法识别
- android画板过程分析,Android涂鸦画板原理详解——从初级到高级(二)