题意:
有一排池塘,从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; }