POJ-2385(DP)

来源:互联网 发布:数据保密性 编辑:程序博客网 时间:2024/06/05 04:19

一、DP的关键点在于状态变量的选取,这里很容易可以令时间点T和转弯次数W作为我们的状态变量,由于双路径,所以还要将在时间点T后所在的路径作为一个状态,令f(t,w,i)表示在经过最多w次转弯后在t时刻在i号树下,这一过程获得的苹果数,则

如果t时刻苹果在1号树下,则f(t,w,0) = 1 + max(f(t-1,w,0), f(t-1,w-1,1))且f(t,w,1) = max(f(t-1,w,1), f(t-1,w-1,0))

如果t时刻苹果在2号树下,则f(t,w,1) = 1 + max(f(t-1,w,1), f(t-1,w-1,0))且f(t,w,0) = max(f(t-1,w,0), f(t-1,w-1,1))

实际上是简单的流水线DP,注意初始化T = 0和W = 0的情况,下面是根据状态转换方程写出的代码:


#include <stdio.h>#define max(a,b) ((a) > (b) ? (a) : (b))#define MAX_T 1000#define MAX_W 30int T, W, id[MAX_T+1];int dp[MAX_T+1][MAX_W+1][2] = {0};int main(){    int i, t, w, turning;    while(scanf("%d%d", &T, &W) == 2){    //input while figure out how many turnings in total        turning = 0;        for(i = 1; i <= T; ++i){            scanf("%d", &id[i]);            if(i > 1 && id[i] != id[i-1]) ++turning;        }    //special judge        if(W >= turning){            printf("%d\n", T);            continue;        }    //pipeline DP        for(w = 0; w <= W; ++w){            dp[0][w][0] = dp[0][w][1] = 0;        }        for(t = 1; t <= T; ++t){            if(id[t] == 1){                dp[t][0][0] = dp[t-1][0][0] + 1;                dp[t][0][1] = dp[t-1][0][1];            }            else{                dp[t][0][0] = dp[t-1][0][0];                dp[t][0][1] = dp[t-1][0][1] + 1;            }        }        for(w = 1; w <= W; ++w){            for(t = 1; t <= T; ++t){                if(id[t] == 1){                    dp[t][w][0] = 1 + max(dp[t-1][w][0], dp[t-1][w-1][1]);                    dp[t][w][1] = max(dp[t-1][w-1][0], dp[t-1][w][1]);                }                else{                    dp[t][w][0] = max(dp[t-1][w][0], dp[t-1][w-1][1]);                    dp[t][w][1] = 1 + max(dp[t-1][w-1][0], dp[t-1][w][1]);                }            }        }        printf("%d\n", max(dp[T][W][0], dp[T][W][1]));    }    return 0;}


0 0
原创粉丝点击