这个状态转移想了会时间,dp[i][j]记录前i分钟学了j分钟的取得的最大的分数,得到方程dp[i][j] = dp[i-k][j-k] + sum[i] - sum[i-k](l<=k<=j) ,这个果断并不是只是一个普通的DP,交上各种TLE,然后发现问题了,应该需要需要优化。这个状态方程神似以前单调队列优化DP的转移方程,只不过改成对角线了,而且只需维护队列的队头即可。对这部分还是不太自信啊,试着写了写,反正感觉写的不太好,WA了多次,乱改了几次后过了。。。不容易啊。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int dp[1001][1001],p[1001],sum[1001],que[1001]; 6 int main() 7 { 8 int i,j,k,n,m,l; 9 while(scanf("%d%d%d",&n,&m,&l)!=EOF) 10 { 11 memset(dp,0,sizeof(dp)); 12 memset(sum,0,sizeof(sum)); 13 for(i = 1;i <= n;i ++) 14 { 15 scanf("%d",&p[i]); 16 sum[i] = sum[i-1] + p[i]; 17 } 18 for(i = 1;i <= n;i ++)//初始化队列 19 que[i] = i; 20 for(i = l;i <= n;i ++) 21 { 22 for(j = l;j <= i&&j <= n-m;j ++) 23 { 24 dp[i][j] = dp[i-1][j]; 25 if(dp[i-l][j-l]-sum[i-l] > dp[que[i-j+1]][que[i-j+1]+j-i]-sum[que[i-j+1]]) 26 { 27 que[i-j+1] = i-l; 28 } 29 if(dp[i][j] < dp[que[i-j+1]][que[i-j+1]+j-i]+sum[i]-sum[que[i-j+1]]) 30 dp[i][j] = dp[que[i-j+1]][que[i-j+1]+j-i]+sum[i]-sum[que[i-j+1]]; 31 } 32 } 33 printf("%d\n",dp[n][n-m]); 34 } 35 return 0; 36 }