dynamic programming

 分治法贪心法,它们都是将问题实例归纳为更小的、相似的子问题,并通过求解子问题产生一个全局最优解。

贪心法的当前选择可能要依赖已经作出的所有选择,但不依赖于有待于做出的选择和子问题。因此贪心法自顶向下,一步一步地作出贪心选择;而分治法中的各个子问题是独立的 (即不包含公共的子子问题),因此一旦递归地求出各子问题的解后,便可自下而上地将子问题的解合并成问题的解。


但不足的是,如果当前选择可能要依赖子问题的解时,则难以通过局部的贪心策略达到全局最优解;如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题。
解决上述问题的办法是利用动态规划。该方法主要应用于最优化问题,找出其中最优(最大或最小)值的解。在求解过程中,该方法也是通过求解局部子问题的解达到全局最优解,但与分治法和贪心法不同的是,动态规划允许这些子问题不独立,(亦即各子问题可包含公共的子子问题),对重复出现的子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算。该方法也允许其通过自身子问题的解作出选择。

动态规划是运筹学的一个分支,是求解决策过程最优化的数学方法。
20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。1957年出版了他的名著Dynamic Programming,这是该领域的第一本著作。
动态规划问世以来,在经济管理、生产调度、工程技术和最优控制等方面得到了广泛的应用。例如最短路线、库存管理、资源分配、设备更新、排序、装载等问题,用动态规划方法比用其它方法求解更为方便。

一道取自网上的例题:

从键盘上输入两个自然数n和k(n<=100,k<=10),12,。。。,n中任取k个数,要求所取的k个数中,任意两个数不能相差1。编程求有多少种取法。

INPUT

6 3

OUTPUT

4

/*(1,3,5),(1,3,6),(1,4,6),(2,4,6)*/

[code]

#include<stdio.h>
int main()
{
    int n,k,i,j,a[100][100];
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        for(i=1;i<=n;i++)
             a[i][1]=i;
        for(i=2;i<=k;i++)
             a[1][i]=0;
        for(i=2;i<=n;i++)
        {
            for(j=2;j<=k;j++)
            {
                if(i<=j)
                     a[i][j]=0;
                else 
                     a[i][j]=a[i-2][j-1]+a[i-1][j];
            }
        }
        printf("%d",a[n][k]);
    }
    return 0;
}

[/code]

//分析

 F(I,j)表示从1I中任取j个数,任意两个数不能相邻:如果取I,则不能取I-1,必须从1I-2中取j-1个数,即F(I-2,j-1).如果不取I,则只能从1I-1中取j个数,即F(I-1,j).F(I,j)= F(I-2,j-1)+ F(I-1,j);

F[I,1]=I;

F[1,I]=0;

 

这个递推式的结果是:矩形的上三角全0(a[1][1]元素除外),第一列为[1~n],其它元素为a[i-2][j-1]+a[i-1][j],最终所要的结果在a[n][k].(为什么是这样,自己多推几步就知道了)

你可能感兴趣的:(算法)