HDU3905 DP

来源:互联网 发布:guts and glory mac 编辑:程序博客网 时间:2024/06/05 03:13

通过这题看出DP的功底还是不行啊,仍需提高。

题意:一节课有N分钟,ZZ需要睡M分钟,每分钟都有其效益值,ZZ若听课,则必须连续听L分钟以上。问能获得的最大效益值。M分钟的睡眠可以不连续
题解:动态规划,状态设计:dp[i][j]表示第i分钟已经睡过j分钟可以获得的最大效益。状态转移可以分第i分钟听课或者睡觉。若第i分钟睡觉,dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]),若听课,对于每个k( 0 <= k <= i - l),求dp[k][j] + sum[i] - sum[k]的最大值。求最大值的时候用一个数组维护,不用另写一个循环。在第i-1次循环时求得的最大值到第i次时,全都加上了a[i](第i分钟的效益值),[0,i-1-l]区间内的最大值可以通过上一轮循环(i-1)的最大值加上第i分钟的效益值得到,然后和dp[i-l][j]+sum[i]-sum[i-l]比较取较大值即为[0,i-l]区间内的最大值。sum[i]是前i分钟总的效益值

code:

#include <cstdio>#include <cstring>#define N 1010#define Max( a, b ) ( a > b ? a : b )using namespace std;int dp[ N ];int cmp[ N ], sum[ N ];void init ( int n ) {memset ( cmp, 0, sizeof ( cmp ) );for ( int i = 1 ; i < n ; ++i ) {sum[ i ] += sum[ i - 1 ];}}int solve ( int n, int m, int l ) {init ( n );for ( int j = 0 ; j <= m ; ++j ) {int div = j;memset ( dp, 0, sizeof ( dp ) );for ( int i = j + 1 ; i <= n ; ++i ) {dp[ i ] = Max ( dp[ i ], cmp[ i - j ] );if ( i - l < j ) continue;if ( dp[ div ] + sum[ i - 1 ] - sum[ div - 1 ] <dp[ i - l ] + sum[ i - 1 ] - sum[ i - l - 1 ] ) {div = i - l;}dp[ i ] = Max ( dp[ i ], dp[ div ] + sum[ i - 1 ] - sum[ div - 1 ] );cmp[ i - j ] = Max ( cmp[ i - j ], dp[ i ] );}}return dp[ n ];}int main () {int n, m, l;while ( scanf ( "%d%d%d", &n, &m, &l ) != EOF ) {for ( int i = 0 ; i < n ; ++i ) {scanf ( "%d", &sum[ i ] );}printf ( "%d\n", solve ( n, m, l ) );}return 0;}



原创粉丝点击