动态规划学习总结

动态规划学习总结

首先想要学好动态规划最重要的就是了解什么是动态规划,动态规划是用来求解以时间划分阶段的动态过程的优化问题,就是把一个问题分为若干个阶段,即分为若干个小问题,然后逐个求解的过程
在Vjudge的课程作业中我找到了两个不同的类型的动态规划题型,感觉比较具有代表性(作业地址https://vjudge.net/contest/430905)
类型1,其实就是求最大连续增长序列的最大值,包含题目:C,U(其实U就是简化版的C)
思想:这种题型就是求最大连续增长序列和的最大值的问题,比如一组数1,3,2最大的连续增长序列和的最大值为3,可以是3自己,也可以是1和2的和值,首先根据动态规划原则,将问题分为一个个的小问题,依次求解,这里就是从第一个数开始,依次求以该位置为末尾的最大值,这里dp只需要用一维数组即可解决问题,不过需要使用二重循环,dp[i]的初值为a[i]本身
主要代码如下:

for(i=2;i<=n;i++)
        {
   
         dp[i]=a[i];
           for(int j=1;j<=i;j++){
   
               if(a[i]>a[j]){
   
                  if(dp[j]+a[i]>dp[i])
                     dp[i]=dp[j]+a[i];
                 }
            }
         m=max(m,dp[i]);
        }

从第一个值i开始,一次进行第一重循环,第二重循环的位置j从第一个数开始到第一重循环开始的位置结束,那么,为什么要这么做?因为当在求以第i个数为结尾的最大值时,需要判断与前面的任何一个数的关系,如果满足递增,即a[i]>a[j]成立,再判断j位置最大值加上i位置的值是否大于i位置的最大值(即与之前位置判断结果的大小进行比较),如果成立就执行 dp[i]=dp[j]+a[i];改变i位置的最大值,在每一重第一重循环结束的时候取最大值m=max(m,dp[i]);最后m即所求结果
U:
思路为基本思路,按照该类型的思路求解即可AC,AC代码如下:

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int dp[1010];
int main()
{
   
    int a[1010],n;
    while(cin>>n&&n!=0)
    {
   
        memset(dp,0,sizeof(dp));
        int i,m=0;
        for(i=1;i<=n;i++)
            cin>>a[i];
        dp[1]=a[1];
        for(i=2;i<=n;i++)
        {
   
         dp[i]=a[i];
           for(int j=1;j<=i;j++){
   
               if(a[i]>a[j]){
   
                  if(dp[j]+a[i]>dp[i])
                     dp[i]=dp[j]+a[i];
                 }
            }
         m=max(m,dp[i]);
        }
        cout<<m<<endl;
    }
}

C(加强版的U题):
思路:跟U比起来其实就是需要排序,然后多了一个输出位置的要求,首先排序需要按照小鼠的重量进行排序,输入的时候需要记录下每个小数的原始位置

while(cin>>m[t].w>>m[t].s)
    {
   
        m[t].n=t;
        t++;
    }

这时候使用结构体变量就比较方便,排序只需要排重量即可,排序代码如下(sort函数)

bool cmp(mice a,mice b)
{
   
    if(a.w!=b.w)
    return a.w<b.w;
}

接下来就是类型题目的标准代码:

for(i=1;i<=t;i++)
    {
   
        p[i]=i;
        dp[i]=1;
        for(j=1;j<i;j++)
        {
   
            if(m[i].w!=m[j].w&&m[i].s<m[j].s)
            {
   
                if(dp[i]<dp[j]+1)
                {
   
                    p[i]=j;
                    dp[i]=dp[j]+1;
                }
            }
        }
    }

这里的数组p表示以i为结尾的最大值时,i的上一个位置,用来求解各个位置(temp为排序后的末尾最大值的位置)

i=0;
while(p[temp]!=temp)//到末尾最大值的上一个位置是自己本身时,结束判断语句
    {
   
        postion[i]=m[temp].n;//得出原始位置
        temp=p[temp];//末尾最大值的位置往前推1
        i++;
    }

如果最大值本身不是自己,运行语句,postion[i]表示排序前的各个位置,最后输出

cout<<m[temp].n<<endl;
for(j=i-1;j>=0;j--)
        cout<<postion[j]<<endl;

AC代码如下:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
struct mice
{
   
    int w,s,n;
}m[1005];
int dp[1005]={
   0},p[1005]={
   0};//以i结尾最大数值
bool cmp(mice a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值