zoukankan      html  css  js  c++  java
  • 试题 算法提高 天天向上-dp

    试题 算法提高 天天向上

    问题描述
      A同学的学习成绩十分不稳定,于是老师对他说:“只要你连续4天成绩有进步,那我就奖励给你一朵小红花。”可是这对于A同学太困难了。于是,老师对他放宽了要求:“只要你有4天成绩是递增的,我就奖励你一朵小红花。”即只要对于第i、j、k、l四天,满足i<j<k<l并且对于成绩wi<wj<wk<wl,那么就可以得到一朵小红花的奖励。现让你求出,A同学可以得到多少朵小红花。
    输入格式
      第一行一个整数n,表示总共有n天。第二行n个数,表示每天的成绩wi。
    输出格式
      一个数,表示总共可以得到多少朵小红花。
    样例输入
    6
    1 3 2 3 4 5
    样例输出
    6
    数据规模和约定
      对于40%的数据,n<=50;
      对于100%的数据,n<=2000,0<=wi<=109
    思路:

    分析:
    我们将 dp[i][j] 定义为以a[i]为起点,一直到数组结束为止,所有递增序列长度为j的序列的个数。
    以数组 1 3 2 3 4 5为例:
    dp[3][2]表示从第二个3为起始,一直到5,递增序列长度为2的个数。容易知道,满足这样的序列有2个,34 和 35。所以dp[3][2]=2;

    有了上述的定义,我们就可以得出以下递推公式

    dp[i][j]= ∑dp[k][j-1] (k>i,a[k]>a[i])
    现在,我们只要确定了边界条件,就可以使用动态规划来解决这个问题了。
    容易知道 dp[n-1][1]是边界条件,值为1。
    为了让各位读者对动态规划的过程有更形象的了解,我就以1 3 2 3 4 5 为例,列出开头的几个步骤:

    初始: dp[5][1]=1,其余dp[i][j]=0;
    第二步 : dp[4][1]=1; dp[4][2]=dp[5][1]=1;
    第三步: dp[3][1]=1; dp[3][2]=dp[4][1]+dp[5][1]=2; dp[3][3]=dp[4][2]=1;
    第四步:dp[2][1]=1; dp[2][2]=dp[5][1]+dp[4][1]+dp[3][1]=3; dp[2][3]=dp[3][2]+dp[4][2]=3; dp[2][4]=dp[3][3]=1;
    第五步: dp[1][1]=0; dp[1][2]=dp[4][1]+dp[5][1]=2 (a[k]要大于a[i])
    dp[1][3]=dp[4][2]=1;
    第六步: dp[0][1]=1; dp[0][2]=dp[1][1]+dp[2][1]+dp[3][1]+dp[4][1]+dp[5][1]=5; … dp[0][4]=dp[1][3]+dp[2][3]+dp[3][3] =1+3+1=5;

    dp[i][4]中保存的就是,从i开始,一直到结束,递增序列长度为4的序列的个数。
    因此,只要计算所有的dp[i][4]的和即可。
    注意:要long  long,否则只会通过40%的样例
    代码:
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2001;
    ll a[maxn],dp[maxn][5];
    int main(){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        memset(dp,0,sizeof(dp));
        for(int i=n;i>=1;i--){
            for(int j=2;j<=4;j++){
                dp[i][1] = 1;
                int k=i+1;
                while(k<=n){
                    if(a[k]>a[i])
                        dp[i][j]+=dp[k][j-1];
                    k++;
                }
            
            }
        }
        ll sum=0;
        for(int i=1;i<=n;i++){
            sum+=dp[i][4];
        }
        cout<<sum<<endl;
        return 0;
    }
  • 相关阅读:
    byvoid
    soa文章摘抄
    也谈设计模式,架构,框架和类库的区别
    GoF设计模式三作者15年后再谈模式
    陈梓涵:我们为什么要学习设计模式
    陈梓涵:关于编程的胡扯
    hung task机制
    iscsi target tgt架构
    iscsi target IET架构
    ISCSI工作流程target和initiator
  • 原文地址:https://www.cnblogs.com/lusiqi/p/13766951.html
Copyright © 2011-2022 走看看