zoukankan      html  css  js  c++  java
  • hdu--3905--dp

    状态转移方程不难想 我没想到另外还要开个数组 记录上一次的最优状态 wtf

    主要是另外还要开个temp数组 这样可以减少一层for循环.

    dp[x,y]在前x分钟我睡觉花掉了y分钟的时间 ( x>=y )

    dp[x,y] = dp[x-1,y-1]假如我在x这个时间点正在睡觉 那么我得到价值就是 x-1这个时间点是一样的 而且我的睡觉花掉的时间又相比 x-1这个时间点 增加了1分钟

    //dp[x,y] = max( dp[x,y] , dp[x-L]+sum[x]-sum[x-L])在x这个时间点我在听课 这边需要遍历所有的 1-x-L

    上面的方程注释掉 我觉得这写的有点误导人 虽然后面又写上了遍历范围

    这样写 比较好

    x>=L+y的前提下

    dp[x,y] = max( dp[x,y] , dp[k][y] + sum[x]-sum[k] )  1 <=k <= x-L

    其实 你可以发现 dp[k][y] + sum[x]-sum[k] 在 1<=k<=x-L-1之前 这些不就是 上一层 dp[x-1,y]所得出的吗 我们只是多增加了一个 x 这个时间点

    就是 dp[x-L][y] + sum[x]-sum[x-L]

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int n , m , L;
     7 const int size = 1010;
     8 int point[size];
     9 int sum[size];
    10 int temp[size][size];
    11 int dp[size][size];
    12 
    13 void solve( )
    14 {
    15     for( int i = 1 ; i<=n ; i++ )
    16     {
    17         for( int j = 0 ; j<=m&&j<=i ; j++ )
    18         {    
    19             if( j>=1 )
    20                 dp[i][j] = dp[i-1][j-1];
    21             if( i>=j+L )
    22                 temp[i][j] = max( temp[i-1][j]+point[i] , dp[i-L][j]+sum[i]-sum[i-L] );
    23             if( i>=L )
    24                 dp[i][j] = max( dp[i][j] , temp[i][j] );
    25         }
    26     }
    27 }
    28                                                          
    29 int main()
    30 {
    31     cin.sync_with_stdio(false);
    32     while( cin >> n >> m >> L )
    33     {
    34         sum[0] = 0;
    35         memset( dp , 0 , sizeof(dp) );
    36         memset( temp , 0 , sizeof(temp) );
    37         for( int i = 1 ; i<=n ; i++ )
    38         {
    39             cin >> point[i];
    40             sum[i] = point[i] + sum[i-1];
    41         }
    42         solve( );
    43         cout << dp[n][m] << endl;
    44     }
    45     return 0;
    46 }
    View Code

     其实temp完全可以写成一维的就足够了 因为记录的只是上一层的最优状态 滚动数组的味道.

    注意下 因为point肯定为正值 所以 睡觉时间肯定是m   连续听课是least L  所以我们可以连续听课时间的时间区间长度是 >=L 我觉得这点很重要 而不是恰好为L 我一开始理解错了

  • 相关阅读:
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 695 岛屿的最大面积(DFS)
    Java实现 LeetCode 695 岛屿的最大面积(DFS)
    PHP serialize() 函数
    PHP print_r() 函数
  • 原文地址:https://www.cnblogs.com/radical/p/4119409.html
Copyright © 2011-2022 走看看