算法分析--动态规划

动态规划

一、动态规划的基本思想

求解问题分为多个阶段或多个子问题,然后按顺序求解各个问题,最后一个子问题就是初始问题的解。
动态规划=贪婪策略+递推+存储递推结果
空间换取时间
基本要素:
最优化子结构性质和重叠子问题性质

二、主要概念

阶段:把问题分为几个相互联系的有顺序的几个环节,这些称为阶段。
状态:某一阶段发出的位置称为状态。
决策:从某一阶段的一个状态演变到下一个阶段的某一个状态的选择。
状态转移方程

三、适合解决的问题

最优化原理:最优子结构
无后向性:某状态一旦确定后,就不受这个状态以后决策的影响。

四、步骤

(1)划分阶段(2)选择状态(3)确定决策并写出状态转移方程

五、PPT例题

1.数塔问题
一个数塔,可以选择向左或者向右走,要求走出一条路径,数值和最大。
状态转移方程:

//状态转移方程
            if(a[i+1][j]>a[i+1][j+1]){
                a[i][j]=a[i][j]+a[i+1][j];
            }
            else{
                a[i][j]=a[i][j]+a[i+1][j+1];
            }
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    int a[100][100];
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            cin>>a[i][j];
        }
    }
    //自下而上
    for(int i=n-1;i>=1;i--){
        for(int j=1;j<=i;j++){
            //状态转移方程
            if(a[i+1][j]>a[i+1][j+1]){
                a[i][j]=a[i][j]+a[i+1][j];
            }
            else{
                a[i][j]=a[i][j]+a[i+1][j+1];
            }
        }
    }
    cout<<a[1][1];

}

2.n个矩阵连乘问题
不会
3.求两个字符串的最长公共字符子序列
详情见这里
4.求一个数列最长不降子序列
详情见这里
5.0-1背包问题
给定的n种物品和一个背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,是的其物品价值最大。
状态方程:
//状态转移方程

   if(j<weight[i]){
        m[i][j]=m[i-1][j];
    }
    else{
        m[i][j]=max(m[i-1][j],value[i]+m[i-1][j-weight[i]]);
#include <bits/stdc++.h>
using namespace std;
const int MAX=10000;
int n;//物品的数量
int c;//包的容量
int value[MAX];//物品的价值
int weight[MAX];//物品的重量
int m[MAX][MAX];//求解
int main(){
    cin>>n>>c;
    for(int i=1;i<=n;i++){
        cin>>value[i]>>weight[i];//输入商品的重量和价值
    }
    memset(m,0,sizeof(m));//初始化为0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=c;j++){
                //状态转移方程
                if(j<weight[i]){
                    m[i][j]=m[i-1][j];
                }
                else{
                    m[i][j]=max(m[i-1][j],value[i]+m[i-1][j-weight[i]]);
                }

        }
    }
    cout<<m[n][c];//输出最终值
}

6.最大字段和
给定n个元素的整数列,找到其中字段,使得其和最大
状态转移方程

dp[i]=max(a[i],dp[i-1]+a[i]);
#include <bits/stdc++.h>
using namespace std;
int mian(){
    int n;
    int a[100]={0};
    int dp[100]={0};
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i=0;i<n;i++){
        dp[i]=max(a[i],dp[i-1]+a[i]);
    }
    int k=0;
    for(int i=1;i<n;i++){
        if(dp[i]>dp[k]){
            k=i;
        }
    }
    cout<<dp[k];
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值