动态规划

来源:互联网 发布:沙盘软件多开器 编辑:程序博客网 时间:2024/06/08 07:51
动态规划的介绍
    动态规划一般也只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。简单地说,问题能够分解成子问题来解决。

动态规划算法的4个步骤:
1.描述最优解的结构
2.递归定义最优解的值
3.按自底向上的方式计算最优解的值 //此3步构成动态规划解的基础。
4.由计算出的结果构造一个最优解。 //此步如果只要求计算最优解的值时,可省略。

!!!!!将递归变为循环,这就是动态规划!!!!!!!!!!


以下为需要用到动态规划的地方:
一,缓存与动态规划
    例题一:有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
      分析:由题目得出f(n) = f(n-1) + f(n-2)
      解法一:void walk_one(int n)  //此题使用递归算法
            {
                if(n>10)
                {
                    return;
                }
                if(n==10)
                {
                    Count++;
                    return;
                }
                walk_one(n+1);
                walk_one(n+2);
            }
      解法二:int walk_two(int n)  //在递归算法的基础上添加了动态规划的思想,对于需要重复进行的运算进行记忆
            {
                if(n<0)
                {
                    return 0;
                }
                if(n==0)
                {
                    return 1;
                }
                return walk_two(n-1)+walk_two(n-2);
            }
      解法三:int walk_three(int n)  //同上
            {
                if(n>0&&n<=2)  //f(1) = 1; f(2) = 2;
                {
                    return n;
                }
                return walk_two(n-1)+walk_two(n-2);
            }
      解法四:int walk_four()  //舍去递归,根据总结的规律,直接使用循环进行动态规划
            {
                int num[10];
                int i=0;
                num[1] = 2,num[0] = 1;
                for(i=2;i<10;i++)
                {
                    num[i] = num[i-1]+num[i-2];
                }
                return num[9];
            }
    例题二:背包问题
        /*
        背包问题:
        有n个重量和价值分别为weight,value的物品;背包最大负重为W,求能用背包装下的物品的最大价值?
        输入:n =4 W=5
        weight=2, 1, 3, 2
        value =3, 2, 4, 2
        输出=7*/
        解法一:
        //!!!!!!!!!!!!!!!!!!里面含有重复计算,耗费大量时间!!!!!!!!!!!!!!!!!!!!!//
            #include <stdio.h>
            #define MAX(a,b) a>b?a:b
            #define M 10
            int v[M]={0},w[M]={0};
            int num=0;
            int main(void)
            {
                int find(int,int);
    
                int i=0;
                int big=0;
                scanf("%d %d",&num,&big);
                for(i=0;i<num;i++)
                {
                    scanf("%d %d",w+i,v+i);
                }
                printf("%d\n",find(0,big));
                return 0;
            }

            int find(int i,int have)
            {
                int res;
                if(have<=0||i>=num)
                {
                    return 0;
                }
                if(have<w[i])
                {
                    res = find(i+1,have);
                }
                else
                {
                    res = MAX(find(i+1,have),find(i+1,have-w[i])+v[i]);
                }
                return res;
            }
        解法二:
            //递归转换成循环
            int find_2(int bag)
            {
                int i=0,j=0;
                int dp[M][M]={0}; //背包考虑放置i物品时,剩余背包容量为j;如果j的值小于此时i的体积,直接跳到下一个物品。
                for(i=num-1;i>=0;--i) //如果j>i的体积,则考虑是放置i产生的价值大还是不放置价值大。
                {
                    for(j=0;j<=bag;++j)
                    {
                        if(j<w[i])  
                            dp[i][j] = dp[i+1][j];
                        else
                            dp[i][j] = MAX(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
                    }
                }
                return dp[0][bag];
            }
原创粉丝点击