分治法+动态规划+贪心算法!!(小白总结,求指教)
本人还是编程小小白一个,因学习需要想总结一下几种算法,膜拜很多大佬的文章,还请大佬们指教!!!
分治法:
概念:将问题分解为一些规模更小且相似的子问题,并且这些子问题可以逐个击破,且这些子问题的解答可以合并为最终问题的解答。
特征:1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
动态规划算法:
概念:动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使问题能够以递推(或者是分治)的方式解决。
特征:1)最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,既满足最优化原理。
2)无后效性:即某阶段状态一旦确定,就不受这个状态以后的决策的影响。也就是说,某状态以后的过程不会影响以前的状态,至于当前状态有关
3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势
典型例题:(只总结了简单dp的题目)
一、递推类:递推类一般形式单一,但方法各有不同。
题一:数塔
有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
分析:这道题目只是动态规划中很简单的一到题目。刚拿到题目我们可能会想采用贪心算法(稍后会介绍),但是简单的用贪心算法没有办法满足这个题目的要求,每一步都会受到下一步的影响,没有办法找到那个最大的路径。
所以我们采用的方法是,由底层向顶层递推的动态规划算法。比如第四层,如果第四层选择的是2,那么第五层选择的一定是19,如果第四层选择的是18,那么第五层选择的一定是10;以此类推,每一层选择完毕便不再影响后续的判断。
代码实现如下:
#include<iostream>
#include<algorithm>
using namespace std;
int n;//全局定义n为层数
int st[100][100];//存放数塔值的数组
int temp[100][100]; //中间计算数塔最大值的数组
void maxst()
{
for(int j=0;j<n;j++)
temp[n-1][j]=st[n-1][j];
for(int i=n-2;i>=0;i--)
{
for(int j=0;j<=i;j++)
temp[i][j]=st[i][j]+max(temp[i+1][j],temp[i+1][j+1]);
}
}
void printmax()
{
cout<<temp[0][0]<<endl;
cout<<st[0][0]<<' ';
int j=0;
for(int i=1;i<n;i++)
{
if((temp[i-1][j]-st[i-1][j])==temp[i][j+1]) j++;
cout<<st[i][j]<<' ';
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<=i;j++)
cin>>st[i][j];
}
maxst();
printmax();
return 0;
}