动态规划

动态规划(Dynamic Programming)是是运筹学的一个分支,是求解决策过程最优化的数学方法。 动态规划被用于解决多阶段最优化决策问题。它的基本思路是将待解决的问题划分成多个阶段,每个阶段可能存在多种不同的状态。如果划分阶段后的问题满足最优子结构,则可以用动态规划算法一个阶段一个阶段,一个状态一个状态地解决问题的所有子问题,继而解决原问题。(罗嗦的概念)

动规分为几部分

阶段

阶段的划分是人为的。但是必须满足在一个阶段的任意状态做出任何决策后,得到的新状态都属于之后的阶段。(甚至不能在原阶段停留) 不过实际问题中,有的时候阶段并不是线性的,有的时候你很难描述阶段,但是实际上阶段只是提供了一个解决问题的顺序和设计状态的思路,设计出合理高效的状态才是解决问题的关键。 即:阶段的最大作用是辅助状态设计。

状态

到达某个过程,处于某个状态。一个状态是一个事件,并且包含一切会对决策产生影响的限制条件。

子问题

把一个大的问题化为越来越简单的子问题,通过状态转移方程对大问题求解。子问题与原问题非常相似,或者说根本就是同一个问题,相同的限制条件,相同的最终目的,只是改变了问题的规模,而解决问题需要的方法,也许可以完全仿照原问题。看到这里,你想到了什么?递归!搜索!

决策

决策是一个集合。不同的状态可能有不同的决策集合。但是同一个状态一定有相同的决策集合。

转移

转移用来描述两个子问题之间的关系,A子问题对应的状态进行决策C能到转化为B子问题,称为A→B有C转移。

废话不多说看题(虽然说了不少

1258:【例9.2】数字金字塔


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 11942     通过数: 6782 

【题目描述】

观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。

在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。

【输入】

第一个行包含R(1≤ R≤1000),表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

所有的被供应的整数是非负的且不大于100。

【输出】

单独的一行,包含那个可能得到的最大的和。

【输入样例】

5
13
11 8
12 7  26
6  14 15 8
12 7  13 24 11

【输出样例】

86
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[1001][1001],f[1001][1001];
int main()
{
	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++)
		f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j]; //状态转移方程不难看懂
	 } 
	 cout<<f[1][1];
}

1259:【例9.3】求最长不下降序列


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 14765     通过数: 4732 

【题目描述】

设有由n(1n200)n(1≤n≤200)个不相同的整数组成的数列,记为:b(1)b(2)b(n)b(1)、b(2)、……、b(n)若存在i1<i2<i3<<iei1<i2<i3<…<ie 且有b(i1)b(i2)b(ie)b(i1)≤b(i2)≤…≤b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。

例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中13,16,18,19,21,22,63就是一个长度为7的不下降序列,同时也有7 ,9,16,18,19,21,22,63组成的长度为8的不下降序列。

【输入】

第一行为n,第二行为用空格隔开的n个整数。

【输出】

第一行为输出最大个数max(形式见样例);

第二行为max个整数形成的不下降序列,答案可能不唯一,输出一种就可以了,本题进行特殊评测。

【输入样例】

14
13 7 9 16 38 24 37 18 44 19 21 22 63 15

【输出样例】

max=8
7 9 16 18 19 21 22 63
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[201],f[201],c[201];
int main()
{
	int n,maxx=0xc0c0c0c0;
	int k;
	cin>>n;
	for(int i=1;i<=n;i++)
	f[i]=1;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	for(int i=2;i<=n;i++)
		for(int j=1;j<i;j++)
		{
			if(a[i]>=a[j])
				if(f[i]<f[j]+1)
					f[i]=f[j]+1;
		} 
	for(int i=1;i<=n;i++)
			if(f[i]>maxx)
			{
				maxx=f[i];
				k=i;
			}
	cout<<"max="<<maxx<<endl;
 	int q=1,m=maxx,ii=k-1;
    c[1]=k;
    while(m>1)
    {
        if(f[ii]==m-1&&a[ii]<=a[k])
        {
            c[++q]=ii;
            k=ii;
            m--;
        }
        ii--;
    }
    for(ii=q;ii>0;ii--)
        printf("%d ",a[c[ii]]);
}
 
原文地址:https://www.cnblogs.com/zhaoxuelin/p/12403826.html