poj 1042 Gone Fishing(dp + 回溯)

目录

题目:

题意:

一解:DP+回溯

状态转移方程:

AC代码:

 


题目:

Gone Fishing

Time Limit: 2000MS   Memory Limit: 32768K
Total Submissions: 38276   Accepted: 11894

Description

John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachable along a single, one-way road. John starts at lake 1, but he can finish at any lake he wants. He can only travel from one lake to the next one, but he does not have to stop at any lake unless he wishes to. For each i = 1,...,n - 1, the number of 5-minute intervals it takes to travel from lake i to lake i + 1 is denoted ti (0 < ti <=192). For example, t3 = 4 means that it takes 20 minutes to travel from lake 3 to lake 4. To help plan his fishing trip, John has gathered some information about the lakes. For each lake i, the number of fish expected to be caught in the initial 5 minutes, denoted fi( fi >= 0 ), is known. Each 5 minutes of fishing decreases the number of fish expected to be caught in the next 5-minute interval by a constant rate of di (di >= 0). If the number of fish expected to be caught in an interval is less than or equal to di , there will be no more fish left in the lake in the next interval. To simplify the planning, John assumes that no one else will be fishing at the lakes to affect the number of fish he expects to catch. 
Write a program to help John plan his fishing trip to maximize the number of fish expected to be caught. The number of minutes spent at each lake must be a multiple of 5.

Input

扫描二维码关注公众号,回复: 3537996 查看本文章

You will be given a number of cases in the input. Each case starts with a line containing n. This is followed by a line containing h. Next, there is a line of n integers specifying fi (1 <= i <=n), then a line of n integers di (1 <=i <=n), and finally, a line of n - 1 integers ti (1 <=i <=n - 1). Input is terminated by a case in which n = 0.

Output

For each test case, print the number of minutes spent at each lake, separated by commas, for the plan achieving the maximum number of fish expected to be caught (you should print the entire plan on one line even if it exceeds 80 characters). This is followed by a line containing the number of fish expected. 
If multiple plans exist, choose the one that spends as long as possible at lake 1, even if no fish are expected to be caught in some intervals. If there is still a tie, choose the one that spends as long as possible at lake 2, and so on. Insert a blank line between cases.

Sample Input

2 
1 
10 1 
2 5 
2 
4 
4 
10 15 20 17 
0 3 4 3 
1 2 3 
4 
4 
10 15 50 30 
0 3 4 3 
1 2 3 
0 

Sample Output

45, 5 
Number of fish expected: 31 

240, 0, 0, 0 
Number of fish expected: 480 

115, 10, 50, 35 
Number of fish expected: 724 

题意:

有n个岛,每个岛可以钓鱼,钓鱼的量为f[i],每过单位时间每个岛的钓鱼量会减少r[i],去下一个岛需要花费时间为t[i]。求总钓鱼量最大时,在每个岛屿停留时间,和最大钓鱼量(注意单位时间为5分钟)。

一解:DP+回溯

写这一题的时候学习了一下大佬的写题风格(一切用函数使代码看起来清晰),感觉看习惯还可以。

DP的做法应该是看到这个题目的第一想法,这一题有很明显的状态转移方程

状态转移方程:

dp[i][j]=max(dp[i][j-1]+sum(j,j-k-t[i]),dp[i][j-1]+temp)\left \{ k<=j-t[i] \right \}\left \{temp=f[i]-r[i]*path[i][j-1]\right \}

由于要输出规划方案,使用使用一个path数组记录路径,同时path数组的使用也大大优化了我们控制减少量的操作。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<vector>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int dp[26][300],f[26],r[26],t[26];
int path[26][300],cost[26];
bool flag = false;
int n,h,temp,maxn,index;
inline int get_sum(int i,int t)
{
    return ((f[i] << 1) - r[i] * (t - 1)) * t / 2;
}
inline int get_cost(int i,int j)
{
    return (f[i] - r[i] * path[i][j - 1]) > 0 ? (f[i] - r[i] * path[i][j - 1]) : 0;
}
void input()
{
    scanf("%d",&h);
    for(int i = 1;i <= n;++i) scanf("%d",&f[i]);
    for(int i = 1;i <= n;++i) scanf("%d",&r[i]);
    for(int i = 2;i <= n;++i) scanf("%d",&t[i]);
}
void init()
{
    h *= 12,maxn = -inf;
    memset(cost,0,sizeof cost);
    memset(path,-1,sizeof path);
    memset(dp,-1,sizeof dp);
    for(int i = 0;i <= n;++i) dp[0][i] = 0;
    t[1] = 0;
}
void DP_move(int i,int j,int k)
{
    if(dp[i - 1][k] != -1 && dp[i - 1][k] + get_sum(i,j - k - t[i]) >= dp[i][j]){
            dp[i][j] = dp[i - 1][k] + get_sum(i,j - k - t[i]);
            path[i][j] = j - k - t[i];
        }
        if(j > 0 && path[i][j - 1] != -1 && dp[i][j] < dp[i][j - 1] + get_cost(i,j)){
            dp[i][j] = dp[i][j - 1] + get_cost(i,j);
            path[i][j] = path[i][j - 1] + 1;
        }
}
void DP()
{
    for(int i = 1;i <= n;++i)
        for(int j = t[i];j <= h;++j)
            for(int k = 0;k <= j - t[i];++k)
                DP_move(i,j,k);
    for(int i = 0;i <= n;++i) if(maxn < dp[i][h]) {maxn = dp[i][h];index = i;}
}
void dfs(int l)
{
    if(l <= 1) return ;
    cost[l] = path[l][h];
    h -= cost[l] + t[l];
    dfs(l - 1);
}
void output()
{
    if(flag) printf("\n");
    flag = true;
    cost[1] = h;
    for(int i = 1;i < n;++i) printf("%d, ",5 * cost[i]);
    printf("%d\n",5 * cost[n]);
    printf("Number of fish expected: %d\n",maxn);
}
void solve()
{
    DP();
    dfs(index);
    output();
}
int main()
{
    while(scanf("%d",&n) != EOF && n){
        input();
        init();
        solve();
     }
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/qq_41791981/article/details/82013552
今日推荐