POJ 1042:Gone Fishing

题意:

有一排池塘,从i到i+1个池塘需要t[i]时间(我的代码里是t[i+1]), i池塘一次能抓到f[i]只鱼,每抓一次后少d[i]只,到少于等于0时,之后都为0

问告诉你所有信息,求最优情况(最优情况相同时,取前面时间花的多的)

类型:

DP动态规划

思路:

状态含义:

dp[i][v]为第i个池塘还有v时间时,的最优答案

状态转移:

那么对于池塘i,如果它有2中选择

1:其实没到过池塘i

2:到了池塘i并停留k时间

当然,如果要求必须到,那么第一个选择忽略。

初始化:

对于所有i=1,那么所有时间都用来停留在i

特殊:

如果必须到达当前,然而所给的时间少于从上一个池塘来到这个池塘的时间,则IMPOSSIBLE(注意,要先判断这个再初始化)

代码:

/*************************************************************************
    > File Name:    poj1042.cpp
    > Author:       Shine
    > Created Time: 2013-05-19 下午 11:38:29
    > QuestionType: DP动态规划
    > Way: 动态规划
    > Submit: 2WA(1次DP转移错误,1次初始化错误) 3PE(没注意空行) 1AC
    > Gain: 学习练习了DP
    > Experience: DP中还要注意有些情况是不可能的,要返回什么值慎重处理!
                  而且先判断是否可能再操作。
 ************************************************************************/

#include <cstdio>
#include <cstring>
#include <cstdlib>
#define IMPOSSIBLE -999999
int f[30], d[30], t[30];
int dp[30][16*12+10];
bool vis[30][16*12+10];
int yu[30][16*12+10];
int flag[30][16*12+10];

int dfs(int i, int v, int iscome) {
    //如果不是必须要到,则考虑不用到的情况
    //然后考虑到了以后,停留多长时间
    //  如果停留的时间太长,以至于不可能了,那就退出;
    //记录下停留的时间。 返回

    //初始化:  如果必须到,但是时间不够到达上一个节点,则返回IMPOSSIBLE
    //          如果i == 1 ,则返回第一个节点停留v时间能获得的数量l
    if (vis[i][v]) return dp[i][v];
    if (iscome && v-t[i] < 0) {
        vis[i][v] = 1;
        return dp[i][v] = IMPOSSIBLE;
    }
    if (i == 1) {
        vis[i][v] = 1;
        return dp[i][v] = yu[i][v];
    }


    int &ans = dp[i][v] = IMPOSSIBLE;
    if (!iscome) {
        ans = dfs(i-1, v, 0);
        flag[i][v] = -99;
    }

    int k;
    for (k = 0; ; k++){
        if (dfs(i-1, v-t[i]-k, 1) == IMPOSSIBLE) break;
        if (ans < dfs(i-1,v-t[i]-k, 1)+yu[i][k]) {
            ans = dfs(i-1,v-t[i]-k, 1)+yu[i][k];
            flag[i][v] = k;
        }
    }
    vis[i][v] = 1;
    return ans;
}

int main() {
    int n, h;
    while (scanf("%d", &n) != EOF && n) {
        scanf("%d", &h);
        int i ;
        int totaltime = h*12;

        for (i = 1; i <= n; i++) {
            scanf("%d", &f[i]);
        }

        for (i = 1; i <= n; i++) {
            scanf("%d", &d[i]);
        }

        t[1] = 0;
        for (i = 2; i <= n; i++) {
            scanf("%d", &t[i]);
        }

        memset(yu, 0, sizeof(yu));
        for (i = 1; i <= n; i++) {
            int j;
            int fish = f[i];
            //printf("fish = %d\n", fish);
            //printf("yu[%d][0] = %d\n", i, yu[i][0]);
            for (j = 1; j <= totaltime; j++) {
                if (fish <= 0) break;
                yu[i][j] = fish + yu[i][j-1];

//                printf("yu[%d][%d] = %d\n", i, j, yu[i][j]);

                fish -= d[i];
            }
            for (; j <= totaltime; j++) {
                yu[i][j] = yu[i][j-1];
            }
//            getchar();
        }

        memset(dp, -1, sizeof(dp));
        memset(vis, false, sizeof(vis));
        memset(flag, -1, sizeof(flag));
        dfs(n, totaltime, 0);


        int re[30] = {0};
        int time = totaltime;
        for (i = n; i > 1; i--) {
            re[i] = flag[i][time];
            if (re[i] == -99) {
                re[i] = 0;
            } else {
                time -= t[i] + re[i];
            }
        }
        re[1] = time;

        printf("%d", re[1]*5);
        for (i = 2; i <= n; i++) {
            printf(", %d", re[i]*5);
        }
        puts("");
        printf("Number of fish expected: %d\n", dp[n][totaltime]);
        puts("");
    }
    return 0;
}

 

posted on 2013-05-19 23:52  ShineCheng  阅读(234)  评论(0编辑  收藏  举报

导航