LETTers第五场-Sleeping -解题报告

题目描述:

    一节课有n分钟,ZZZ每听一分钟课都能得到一定的分数,一旦她开始听课就必须要至少连续听l分钟,但是她每节课都要有m分钟的睡眠时间(这m分钟不连续),问在不影响她睡觉的情况下, 她一节课最多能得多少分。。。

题面建模:

    dp。

 首先dp[i][j]表示前i分钟有j分钟是睡觉时间, 如果第i分钟睡觉dp[i][j]=dp[i-1][j-1];

   第i分钟学习的话: dp[i][j]=max(dp[k][j]+score[i]-score[k]) (1<=k<=i-l)。 score[i]表示前i分钟的分数之和。

解题要点:

   注意边界的处理和dp数组的初始化,开始的时候应将dp[i][j]=0。

   另外就是求dp[i][j]时如果将k从1到i-l遍历会超时,需要一个memory数组,记录这里求出的最大值,那么转移方程改写为:

   dp[i][j]=Max(mem[i-1][j]+score[i]-score[i-1],dp[i-l][j]+score[i]-score[i-l]);

时空开销分析:

空间复杂度:O(n^2)。

时间复杂度:O(n^2)。

特别说明:

无。

程序:

#include <stdio.h>
#include <string.h>
int score[1010];
int mem[1010][1010];
int dp[1010][1010];
int Max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int n,m,l,i,j;
    while(scanf("%d %d %d",&n,&m,&l)!=EOF)
    {
        memset(score,0,sizeof(score));
        memset(dp,0,sizeof(dp));
        memset(mem,0,sizeof(mem));
        for(i=1;i<=n;i++)
        {
            scanf("%d",score+i);
            score[i]+=score[i-1];
        }
        for(i=1;i<=n;i++)
            for(j=0;j<=m;j++)
            {
                if(i>=l+j)
                    dp[i][j]=Max(mem[i-1][j]+score[i]-score[i-1],dp[i-l][j]+score[i]-score[i-l]);
                 mem[i][j]=dp[i][j];
                if(j>=1)
                    dp[i][j]=Max(dp[i][j],dp[i-1][j-1]);
            }
        printf("%d\n",dp[n][m]);
    }
    return 1;
}

 

posted @ 2012-04-21 10:59  LETTers  阅读(131)  评论(0编辑  收藏  举报