POJ 3661 Running (DP思想)

  今天之所以单独写这道题的解题报告是想总结一下做这道题的思想。个人感觉做dp的话有时候用两个小时体会一道题的思想比用一个小时翻解题报告+看题A掉数道题来的有趣。某大神说,思考是一种美德。。。

  题意:N分钟,小刚每分钟可以选择是停下休息还是往前走,如果选择往前走的话可以在第i分钟走Di,当然,小刚的疲劳值也会增加1。如果选择休息则小刚的疲劳值会每分钟减小1,当小刚停下来以后,小刚只能在疲劳值降到0时才能继续再走。已知小刚的疲劳值最多不能超过M,当小刚度过N分钟后要保证他的疲劳值为0,问小刚最多能走多长的距离。

  分析:先设dp[i][j]表示小明在i分钟,疲劳值为j时所能走的最远距离。

  a)、先看dp[i][0]的情况,表示第i分钟时,疲劳值为0,考虑这个值由哪些情况得到,1、dp[i][0] = dp[i-1][0],这个没有任何问题。2、dp[i][0] = dp[i-j][j]。表示i-j分钟时的疲劳值为j,然后一直休息j分钟把疲劳值降成0。

  b)、现在考虑dp[i][j]的情况,它可以由dp[i-1][j-1] + Di得到,表示第i分钟选择走Di。因为要保证没有后效性,所以只有这一种情况可以转移。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
#include <cmath>
#include <algorithm>


#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for(i = 0; i < n; ++i)
#define FOR(i, l, h)    for(i = l; i <= h; ++i)
#define FORD(i, h, l)   for(i = h; i >= l; --i)
#define L(x)    x << 1
#define R(x)    x << 1 | 1
#define MID(l, r)  (l + r) >> 1
typedef long long LL;

using namespace std;

const int N = 10010;
const int M = 510;

int dp[N][M];
short num[N];

int main() {
    //freopen("data.in", "r", stdin);

    int i, j, n, m;

    scanf("%d%d", &n, &m);
    FOR(i, 1, n)   scanf("%hd", num + i);

    CL(dp, 0);
    FOR(i, 1, n) {
        dp[i][0] = dp[i-1][0];
        FOR(j, 1, m) {
            if(i - j >= 0) {
                dp[i][0] = max(dp[i][0],  dp[i - j][j]);
            }
            dp[i][j] = dp[i-1][j-1] + num[i];
        }
    }
    printf("%d\n", dp[n][0]);
    return 0;
}
posted @ 2012-05-05 22:12  AC_Von  阅读(1027)  评论(0编辑  收藏  举报