第一周 动态规划Dynamic Programming(一)
一、概念
动态规划是运筹学的一个分支,是求解决策过程最优化的数学方法。动态规划是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。
1、试用情况:
2、解决步骤:
1、拆分问题
2、找状态(初始值)
3、状态转移方程
3、DP问题的分类:
1、线性dp 2、背包 3、区间dp 4、数位dp 5、状压dp 6、树形dp 7、概率dp
4、具体典例:
A线性DP:
最长上升子序列(LIS)
/*最长上升子序列LIS---hdu1257*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 100005 using namespace std; int dp[maxn],num[maxn];//dp[i]定义为以ai为结尾的最长上升子序列的长度
int main()
{
int n,i,j,ans;
//freopen("Atext.in","r",stdin);
while(cin >> n)
{
ans=;
for(i=;i<n;i++)
{
cin >> num[i];
dp[i]=; //每一个以ai为结尾的LIS只有两种情况,一种是他自身
} //另一种是它前面比它小的数的LIS加上ai
for(i=;i<n;i++)
{ //dp[i]=1的赋值也可以放到这里
for(j=;j<i;j++) //对每一个ai的前面走到它的路径循环记录
{
if(num[j]<num[i]) //选出以ai结尾的最长的路径保存
dp[i]=max(dp[j]+,dp[i]);
}
ans=max(dp[i],ans); //记录各个路径的最大值,即LIS
}
cout << ans << endl;
/*O(nlogn)的方式--利用二分查找
dp[i]:长度为i+1的上升子序列中末尾元素的最小值(不存在的话就是INF);
fill(dp,dp+n,INF);
for(int i=0;i<n;i++)
{
*lower_bound(dp,dp+n,a[i])=a[i];//找到>=a[i]的第一个元素,并用a[i]替换;
}
cout<<lower_bound(dp,dp+n,INF)-dp<<endl;//找到第一个INF的地址减去首地址就是最大子序列的长度;
*/
}
return ;
}
最长公共序列(LCS)

/*LCS----最长公共子序列*/
#include <bits/stdc++.h> #define maxn 1005
using namespace std;
char s[maxn],t[maxn]; //待判断的字符串数组
int dp[maxn][maxn]; //si与tj对应的公共子序列的长度
int main()
{
int i,j,n,m;
cin >> n >> m;
for(i=;i<n;i++)
cin >> s[i];
for(j=;j<m;j++)
cin >> t[j];
for(i=;i<n;i++)
{
for(j=;j<m;j++)
{
if(s[i]==t[j])
dp[i+][j+]=dp[i][j]+;
else
dp[i+][j+]=max(dp[i][j+],dp[i+][j]);
}
}
cout << dp[n][m] << endl;
return ;
}
//自我心得:感觉无论是01背包还是LCS的二维数组都记录了每一种可能组合的状态,并且是该组合状态下的最优化值
//通过记录每一步状态的转移,一步步递推出最终的结果。
B.背包(有背包九讲):
01背包

/*01背包(递归版)*/
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1005
using namespace std; int n,W; //int dp[n][j]; 第i个物体,背包容量为j时的价值
int w[maxn],v[maxn];
int res(int i,int j) //第i个物体,背包剩余容量j;
{
/*if(dp[i][j]>=0) 记忆化搜索,每种情况只计算一次
return dp[i][j];*/
int ans; //背包里的总价值
if(i==n) //i个物体取或不取得情况都试完了;
ans=;
else if(j<w[i]) //此物体的重量大于背包容量,一定不能取,直接下一个
ans=res(i+,j);
else
{ //取或不取的价值--递归调用
ans=max(res(i+,j),res(i+,j-w[i])+v[i]);
}
//dp[i][j]=ans;参数的组合只有n*W种,计算过的组合就存起来
return ans;
}
int main()
{
int i,j;
//memset(dp,-1,sizeof(dp));
cin >> n >> W; //n个物体,背包容量为W
for(i=;i<n;i++)
cin >> w[i] >> v[i] ;//输入每个物体的容量和价值
cout << res(,W) << endl;//从第i个物体开始,挑选总重小于等于j的部分;
return ;
}
/*01背包(普通版)*/
#include <bits/stdc++.h>
#define maxn 100
using namespace std; int w[maxn],v[maxn];//n个物体的重量及价值
int dp[maxn][maxn]; //前i个物体在背包容量为j的情况下的价值的最大值
int main()
{
int n,W,i,j;
cin >> n >> W;
memset(dp,,sizeof(dp));
for(i=;i<n;i++)
cin >> w[i];
for(j=;j<n;j++)
cin >> v[j];
for(i=;i<n;i++) //无论从前往后递推还是从后往前递推,其实都是记录所有的状态
{
for(j=;j<=W;j++)
{
if(w[i]>j)
dp[i+][j]=dp[i][j]; //dp[i+1][j]:从0到i这i+1个物体中选出总重量不超过j的物体时总价值的最大值
else
dp[i+][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
}
}/*01 背包循环利用单数组实现
for(i=0;i<n;i++)
{
for(j=W;j>=W[i];j--) //循环利用一个数组,只记录前i个物体在背包的各种状态下的最优值。
{ //即dp数组在背包的各个容量下的最优值。
dp[j]=max(dp[j],dp[j-W[i]]+v[i]);
}
} */
cout << dp[n][W] << endl;
return ;
}
//自我心得:n个物体与j容量的背包,组合情况有n*j种,dp二维数组其实就是记录每一种状态下的最优化的值;
//然后通过状态转移方程对状态一步步将结果递推转移出来;
完全背包

#include <bits/stdc++.h>
#define maxn 100
/*完全背包*/
using namespace std;
int dp[maxn][maxn];
int w[maxn],v[maxn];
int main()
{
int n,W,i,j;
cin >> n >> W;
for(i=;i<n;i++)
cin >> w[i];
for(i=;i<n;i++)
cin >> v[i];
for(i=;i<n;i++)
{
for(j=;j<=W;j++)
{
if(j<w[i])
dp[i+][j]=dp[i][j];
else //在dp[i+1][j]的计算中选择k(k>=1)个的情况,与在dp[j+1][j-W[i]]的计算中选择k-1个的情况是相同的。
dp[i+][j]=max(dp[i][j],dp[i+][j-w[i]]+v[i]);
}
}/*
for(int i=0;i<n;i++)
{
for(int j=w[i];j<=W;j++)//针对背包容量dp,只存最优值。
{
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
} */
cout << dp[n][W] << endl;
return ;
}
//自我心得:感觉单数组就是针对每一种背包容量情况,循环n个物体,将dp数组里不断地存入最优化的值
//PS:还可利用滚动数组,当数据限制改变也可用DP针对不同的价值计算最小的重量
//如:dp[i+1][j]:前i个物体中挑出价值总和为j时总重量的最小值。
数位dp及状压dp见(二)……
第一周 动态规划Dynamic Programming(一)的更多相关文章
- 6专题总结-动态规划dynamic programming
专题6--动态规划 1.动态规划基础知识 什么情况下可能是动态规划?满足下面三个条件之一:1. Maximum/Minimum -- 最大最小,最长,最短:写程序一般有max/min.2. Yes/N ...
- 动态规划(Dynamic Programming)算法与LC实例的理解
动态规划(Dynamic Programming)算法与LC实例的理解 希望通过写下来自己学习历程的方式帮助自己加深对知识的理解,也帮助其他人更好地学习,少走弯路.也欢迎大家来给我的Github的Le ...
- 动态规划Dynamic Programming
动态规划Dynamic Programming code教你做人:DP其实不算是一种算法,而是一种思想/思路,分阶段决策的思路 理解动态规划: 递归与动态规划的联系与区别 -> 记忆化搜索 -& ...
- 动态规划 Dynamic Programming
March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...
- [算法]动态规划(Dynamic programming)
转载请注明原创:http://www.cnblogs.com/StartoverX/p/4603173.html Dynamic Programming的Programming指的不是程序而是一种表格 ...
- 动态规划系列(零)—— 动态规划(Dynamic Programming)总结
动态规划三要素:重叠⼦问题.最优⼦结构.状态转移⽅程. 动态规划的三个需要明确的点就是「状态」「选择」和「base case」,对应着回溯算法中走过的「路径」,当前的「选择列表」和「结束条件」. 某种 ...
- 动态规划 Dynamic Programming 学习笔记
文章以 CC-BY-SA 方式共享,此说明高于本站内其他说明. 本文尚未完工,但内容足够丰富,故提前发布. 内容包含大量 \(\LaTeX\) 公式,渲染可能需要一些时间,请耐心等待渲染(约 5s). ...
- 最优化问题 Optimization Problems & 动态规划 Dynamic Programming
2018-01-12 22:50:06 一.优化问题 优化问题用数学的角度来分析就是去求一个函数或者说方程的极大值或者极小值,通常这种优化问题是有约束条件的,所以也被称为约束优化问题. 约束优化问题( ...
- 后台开发 3个题目 array_chunk, 100块钱找零钱(动态规划 dynamic programming), 双向循环链表 llist 删除节点
1. array_chunk 实现 http://php.net/manual/en/function.array-chunk.php <?php function my_array_chunk ...
随机推荐
- 对SVD奇异值分解的理解
首先推荐一篇博客,奇异值分解(SVD)原理详解及推导 - CSDN博客,讲解的很清楚.这里我谈谈自己的理解,方便以后回顾. 如果把向量理解为空间中的一个元素,那么矩阵可以理解为两个空间上的映射 ...
- HDU 2243 Knight Moves
题目: A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find th ...
- [最直白版]一步一步教你用VMware Workstation12安装Ubuntu 16.04和VMware Tools的教程
[最直白版]Win10下一步一步教你用 VMware Workstation12安装Ubuntu 16.04和VMware Tools的教程 安装过程中使用的软件(要保证电脑里面有下列三个东西): 1 ...
- c++---天梯赛---查验身份证
★题目: ★题目分析:本题要求输入一个数字n,随后n行输入n个身份证号码.之后进行进一步的判断把错误的身份证号码输出.如果全部正确输出All passed. ★思路方法: ①按题目要求输入. ②对前1 ...
- asp.net -mvc框架复习(7)-基于MVC搭建用户登录项目框架
整体框架: 一.搭建Model层 1.添加通用数据访问类 2.添加实体类(封装和传递数据,和数据库中数据表对应) 3.添加数据访问类(通常和实体类同名,但是后缀名发生改变) 二.搭建控制器层Contr ...
- Git学习(2)-使用Git 代码将本地文件提交到 GitHub
上次随笔写到git的安装和运用命令窗口创建本地版本库,这次主要讲一下用git代码将本地文件提交到GitHub上. 前提是有一个GitHub账号. 1.创建一个新的版本库,进入到你本地项目的根目录下(我 ...
- 监控服务器ssh登录,并发送报警邮件
最近想监控下云主机的ssh登录情况,所以开始写ssh登录报警监控.实现方式并不难. 一:邮箱申请开启SMTP 在邮箱中选择“设置”----->“账户” 在如下图处开启POP3/SMTP服务,并生 ...
- List源码学习之LinkedList
LinkedList 内部数据接口为一个链表,存储数据可为空可重复. 1.包含主要参数: //集合长度transient int size = 0; /** * 头结点 */ transient No ...
- Assembly oth
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- Centos硬盘IO性能检测命令iostat[转]
Centos硬盘IO性能检测命令iostat[转] 在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching.这个问题,貌似有不少人在问,不过都 ...
