zoukankan      html  css  js  c++  java
  • hdu3905 Sleeping (区间dp)

    Problem Description
    ZZZ is an enthusiastic ACMer and he spends lots of time on training. He always stays up late for training. He needs enough time to sleep, and hates skipping classes. So he always sleeps in the class. With the final exams coming, he has to spare some time to listen to the teacher. Today, he hears that the teacher will have a revision class. The class is N (1 <= N <= 1000) minutes long. If ZZZ listens to the teacher in the i-th minute, he can get Ai points (1<=Ai<=1000). If he starts listening, he will listen to the teacher at least L (1 <= L <= N) minutes consecutively. It`s the most important that he must have at least M (1 <= M <= N) minutes for sleeping (the M minutes needn`t be consecutive). Suppose ZZZ knows the points he can get in every minute. Now help ZZZ to compute the maximal points he can get.
     

    Input
    The input contains several cases. The first line of each case contains three integers N, M, L mentioned in the description. The second line follows N integers separated by spaces. The i-th integer Ai means there are Ai points in the i-th minute.
     

    Output
    For each test case, output an integer, indicating the maximal points ZZZ can get.
     

    Sample Input
    10 3 3 1 2 3 4 5 6 7 8 9 10
     

    Sample Output
    49
     
    题意:一节课有n分钟,Z每听一分钟课都能得到那分钟对应的分数,一旦她开始听课就必须至少连续听L分钟,但是她每节课都要有m分钟的睡眠时间(这m分钟可以不连续),问在睡眠时间不少于m的条件下 她一节课最多能得多少分。
    思路:容易想出dp状态,dp[i][j]表示前i分钟睡j分钟最多能得的分数。那么对第i分钟进行讨论,如果第i分钟睡觉的话,那么dp[i][j]=dp[i-1][j-1];如果第i分钟听课的话,那么[i-l,i]分钟一定是听课的,所以dp[i][j]=max(dp[k][j]+sum[i]-sum[k]).(k>=j && k<=i-L) (注意:这里k不能直接用i-L带进去,而不是枚举1~i-L,错误地认为dp[i][j]=dp[i-L][j]+sum[i]-sum[k],因为dp[i-L][j]的本质含义是在满足如果i-L这一分钟听课,那么这之前L分钟都在听课,但是这里状态转移的时候并不一定需要满足条件,比如i-L,i-L-1这两分钟可以和[i-L+1,i]合并,然后再加上dp[i-L-2],这个状态就不再dp[i-L][j]中)。状态方程写完后我们会发现时间复杂度不足,这里要再开一个dp_tmp数组,用dp_tmp[i][j]来优化max(dp[k][j]+sum[i]-sum[k]),即dp_tmp[k][j]=max(dp[1][j]+v[2]+...+v[k],dp[2][j]+sum[3]+...+sum[k],...dp[k][j] )。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <stack>
    using namespace std;
    #define maxn 1005
    #define inf 999999999
    int v[maxn],sum[maxn];
    int dp[maxn][maxn],dp_tmp[maxn][maxn];
    
    int main()
    {
        int n,m,l,i,j,k;
        while(scanf("%d%d%d",&n,&m,&l)!=EOF)
        {
            sum[0]=0;
            for(i=1;i<=n;i++){
                scanf("%d",&v[i]);
                sum[i]=sum[i-1]+v[i];
            }
            for(i=0;i<=n;i++){
                for(j=0;j<=m && j<=i;j++){
                    dp[i][j]=0;
                    dp_tmp[i][j]=0;
                }
            }
            for(i=0;i<=n;i++){
                if(i>=l)dp[i][0]=sum[i];
                dp[i][i]=0;
            }
            for(i=1;i<=n;i++){
                for(j=1;j<=i && j<=m;j++){
                    dp[i][j]=max(dp[i][j],dp[i-1][j-1] ); //第i分钟睡
                    if(i-l>=j){
                        dp[i][j]=max(dp[i][j],dp_tmp[i-l][j]+sum[i]-sum[i-l] );
                    }
                    if(i-l>=j)     //这里是为算i+1做铺垫,算出dp_tmp[i+1-l][j]
                    dp_tmp[i+1-l][j]=max(dp[i+1-l][j],dp_tmp[i-l][j]+v[i+1-l] );
                }
            }
            printf("%d
    ",dp[n][m]);
        }
        return 0;
    }
    


  • 相关阅读:
    UWP中实现大爆炸效果(二)
    UWP中实现大爆炸效果(一)
    c# 【电影搜索引擎】采集电影站源码
    安利一个聚合搜索导航站,及怎么样设置成默认的搜索引擎
    女朋友经常问影视剧, 答不上来怎么办?
    宝塔linux面板, 服务器日志分析与流量统计这款插件的mysql版优化。
    苹果cms自动采集,重复执行遇到“上次执行时间: --跳过”的解决办法
    苹果cms, 后台设置保存不了的解决办法
    解决 C:WINDOWSsystem32inetsrv ewrite.dll 未能加载。返回的数据为错误.
    img error 图片加载失败的最佳方案
  • 原文地址:https://www.cnblogs.com/herumw/p/9464545.html
Copyright © 2011-2022 走看看