动态规划_C#
参考网址:https://blog.csdn.net/lvcoc/article/details/104167648
先不管动态规划,先看斐波那契数列
斐波那契数列:F1=Fn-1+Fn-2
分别用递归和非递归实现一下
递归
//递归
public int FibnacciA(int n)
{
int res;
if (n == 1 || n == 2)
res = 1;
else
res = (FibnacciA(n - 1) + FibnacciA(n - 2));
return res;
}
非递归
//非递归
public int FibnacciB(int n)
{
List<int> f = new List<int>() { 0, 1, 1 };//斐波那契数列先初始化前3个特殊的
if (n>2)
{
//n=3 计算1次 n=5 计算3次
for (int i = 0; i < n-2; i++)
{
int fl= f.Count;
f.Add(f[fl - 1] + f[fl - 2]);
}
}
return f[n];
}
经过测试都是对的,但是重点不是这个,重点是运行时间
很明显非递归快的多,而且递归50或者100的时候,我直接卡死了。为啥
因为递归方法里有很多子问题的重复计算,而且数字越大,子问题重复越严重
而非递归的方法里子问题不会重复,而是存起来了
那么非递归的那个方法就可以称为动态规划(DP)
能够动态规划的问题需要两个关键点 1有递推式 2有重复子问题
钢条切割问题
某公司出售钢条,出售价格与钢条长度之间的关系如下表:
问题:现有一段长度为n的钢条和上面的价格表,求切割钢条方案,使得总收益最大。
举个栗子,下面列出的是0-10的最优收益
长度1的时候不用切就是1,长度2的时候可以切1+1,可以不切5,得到5,长度3的时候,首先不切是8,切1和2,2还可以切,但是2其实我们之前已经切过了,最优是5,所以不用继续考虑了,1和2就是1+5=6,最优是8,直接看长度8的时候,可以不切20,
可以切1和7,7之前也考虑过了是17,所以1和7就是1+18=19,最后发现最优是2和6,也就是5+17=22。
到这里其实我们发现这是一个递归的问题。那么我们需要一个递推式
递推式 R(n)=Max(P(n),R(1)+R(n-1),R(2)+R(n-2),.....,R(n-1)+R(1));
//递推式 R(n)=Max(P(n),R(1)+R(n-1),R(2)+R(n-2),.....,R(n-1)+R(1));
public int CutRodA(int n)
{
int[] P = new int[] { 0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 };//价格表
int res = 0;
if (n == 0)
res= 0;
else
{
res = P[n];//不切
for (int i = 1; i < n; i++)
{
res = Mathf.Max(res,CutRodA(i)+CutRodA(n-i));
}
}
return res;
}
测试一下
其实这个递推式还可以再简化,就是
从钢条的左边切割下长度为i的一段,只对右边剩下的一段继续进行切割,左边的不再切割
递推式就变成
public int CutRodB(int n)
{
int[] P = new int[] { 0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 };//价格表
int res = 0;
if (n == 0)
res = 0;
else
{
res = P[n];//不切
//1<=i<=max
for (int i = 1; i < n+1; i++)
{
res = Mathf.Max(res, P[i] + CutRodA(n - i));
}
}
return res;
}
测试一下
但是 ,这两种方法都是自顶向下递归,会产生子问题重复,而且也是钢条越长,子问题重复越厉害
自顶向下从n开始,问题越分越细
也就是4需要3210,3需要210,越分越细
那么1有递推式,2有重复子问题,我们就可以用动态规划了,自底向上实现
//自底向上
public int CutRodC(int n)
{
int[] P = new int[] { 0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 };//价格表
List<int> r = new List<int>();//还是需要一个列表存子问题
r.Add(0);//0长度收益0
for (int i = 1; i < n + 1; i++)//自底向上从1开始存子问题
{
int res = 0;//每次需要重新计算收益
//利用的是简化的递推式2,对于这个循环i就是n,j就是i
for (int j = 1; j < i + 1; j++)
{
//本来r[i-j]也就是n-1,是需要递归,但是因为我们已经存过了,直接取就好了
res = Mathf.Max(res,P[j]+r[i-j]);
}
r.Add(res);
}
return r[n];
}
我尽力注释了,但是还是可能有点绕,需要好好理解
测试一下他们的时间
动态规划明显快了很多
如果你想测试更长的钢条,你需要自己定制一个相应长度的价格表
————————————————
版权声明:本文为CSDN博主「lvcoc」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lvcoc/article/details/104167648
动态规划_C#的更多相关文章
- PJ可能会用到的动态规划选讲-学习笔记
PJ可能会用到的动态规划选讲-学习笔记 by Pleiades_Antares 难度和速度全部都是按照普及组来定的咯 数位状压啥就先不讲了 这里主要提到的都是比较简单的DP 一道思维数学巧题(补昨天) ...
- 增强学习(三)----- MDP的动态规划解法
上一篇我们已经说到了,增强学习的目的就是求解马尔可夫决策过程(MDP)的最优策略,使其在任意初始状态下,都能获得最大的Vπ值.(本文不考虑非马尔可夫环境和不完全可观测马尔可夫决策过程(POMDP)中的 ...
- 简单动态规划-LeetCode198
题目:House Robber You are a professional robber planning to rob houses along a street. Each house has ...
- 动态规划 Dynamic Programming
March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- C#动态规划查找两个字符串最大子串
//动态规划查找两个字符串最大子串 public static string lcs(string word1, string word2) { ...
- C#递归、动态规划计算斐波那契数列
//递归 public static long recurFib(int num) { if (num < 2) ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- 【BZOJ1700】[Usaco2007 Jan]Problem Solving 解题 动态规划
[BZOJ1700][Usaco2007 Jan]Problem Solving 解题 Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...
随机推荐
- python使用笔记17--异常处理
什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常. 异常是Python对象,表示一个错误. 当Pyth ...
- DHCP与配置命令
1. DHCP简介 2. DHCP主要用途 3. 使用DHCP的好处 4.DHCP经典应用模式 5.DHCP交互过程 DHCP的IP地址自动获取工作原理 6.DHCP中继 应用场景 工作原理 ...
- flex布局制作自适应网页
网页布局是css的一个重点应用.传统的布局都是依赖display.position.float属性来实现的,但是特殊布局就不易实现,如垂直居中. 01 flex布局是什么? Flex 是 Flexi ...
- python + pytest基本使用方法(拓展库)
一.测试钩子配置文件 import pytest# conftest.py 是pytest特有的本地测试配置文件;# 既可以用来设置项目级别的Fixture,也可用来导入外部插件,还可以指定钩子函数# ...
- Requests方法 -- Http协议的短链接与长连接介绍
转载于简书: 作者:熊师傅链接:https://www.jianshu.com/p/3fc3646fad80 1.以前的误解 很久之前就听说过长连接的说法,而且还知道HTTP1.0协议不支持长连接,从 ...
- ThinkPHP3.2.3使用PHPExcel类操作excel导出excel
如何导入excel请看:ThinkPHP3.2.3使用PHPExcel类操作excel导入读取excel // 引入PHPExcel类 import("Org.Util.PHPExccel& ...
- JAVA-Scaneer对象
Scanner对象 我们可以通过scanner来获取用户的输入 基本语法 Scanner s = new Scanner(System.in); nextLine():输入 import java.u ...
- Rowid和Rownum
Rowid和Rownum对于数据库开发人员来说基本很少用到,因为在企业数据库开发中大多都是进行数据批处理,但是对于其他数据库人员来说还是会用到的. rowid和rownum都是虚列,但含义完全不同.r ...
- PASS-单组目标值法的样本量计算
临床试验的参数估计中,评价指标有确定的估计目标 ,临床试验目的需通过参数估计(含相应的可信区间估计)的方法证明评价指标不低于目标值时,可根据单组目标值法样本量公式计算. 例:欲证明器械A的诊断准确性非 ...
- 题解 P6688 可重集
己所欲者,杀而夺之,亦同天赐 解题思路 一定不要用自动溢出的 Hash!!!!!!! 我真的是调吐了... 思路非常简单明了 : 需要我们创新一下 Hash. 首先我们的 Hash 要满足无序性.. ...