题目描述:
一节课有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;
}