• POJ3186 Treats for the Cows —— DP


    题目链接:http://poj.org/problem?id=3186

    Treats for the Cows
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 6548   Accepted: 3446

    Description

    FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast amounts of milk. FJ sells one treat per day and wants to maximize the money he receives over a given period time. 

    The treats are interesting for many reasons:
    • The treats are numbered 1..N and stored sequentially in single file in a long box that is open at both ends. On any day, FJ can retrieve one treat from either end of his stash of treats.
    • Like fine wines and delicious cheeses, the treats improve with age and command greater prices.
    • The treats are not uniform: some are better and have higher intrinsic value. Treat i has value v(i) (1 <= v(i) <= 1000).
    • Cows pay more for treats that have aged longer: a cow will pay v(i)*a for a treat of age a.
    Given the values v(i) of each of the treats lined up in order of the index i in their box, what is the greatest value FJ can receive for them if he orders their sale optimally? 

    The first treat is sold on day 1 and has age a=1. Each subsequent day increases the age by 1.

    Input

    Line 1: A single integer, N 

    Lines 2..N+1: Line i+1 contains the value of treat v(i)

    Output

    Line 1: The maximum revenue FJ can achieve by selling the treats

    Sample Input

    5
    1
    3
    1
    5
    2

    Sample Output

    43

    Hint

    Explanation of the sample: 

    Five treats. On the first day FJ can sell either treat #1 (value 1) or treat #5 (value 2). 

    FJ sells the treats (values 1, 3, 1, 5, 2) in the following order of indices: 1, 5, 2, 3, 4, making 1x1 + 2x2 + 3x3 + 4x1 + 5x5 = 43.

    Source

     
     
     
    一.正向思维:
    1.dp[l][r]表示:左边取了l个, 右边取了r个的最大值。
    2.枚举左边取了多少个, 再枚举右边取了多少个。
    3.对于当前的 dp[l][r],它可以是在dp[l-1][r]的基础上取了a[l];也可以是在dp[l][r-1]的基础上取了a[n+1-r]。所以:
    dp[l][r] = max(dp[l-1][r]+a[l], dp[l][r-1]+a[n+1-r])
    

    当然,还需要注意边界条件:l-1>=0,r-1>=0

     
    代码如下:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 #define ms(a,b) memset((a),(b),sizeof((a)))
    13 using namespace std;
    14 typedef long long LL;
    15 const double EPS = 1e-8;
    16 const int INF = 2e9;
    17 const LL LNF = 2e18;
    18 const int MAXN = 2e3+10;
    19 
    20 int n;
    21 int a[MAXN], dp[MAXN][MAXN];
    22 
    23 int main()
    24 {
    25     while(scanf("%d", &n)!=EOF)
    26     {
    27         for(int i = 1; i<=n; i++)
    28             scanf("%d", &a[i]);
    29 
    30         memset(dp, 0, sizeof(dp));
    31         for(int l = 0; l<=n; l++)
    32         for(int r = 0; l+r<=n; r++)
    33         {
    34             if(l!=0) dp[l][r] = max(dp[l-1][r]+(l+r)*a[l], dp[l][r]);
    35             if(r!=0) dp[l][r] = max(dp[l][r], dp[l][r-1]+(l+r)*a[n+1-r]);
    36         }
    37 
    38         int ans = -INF;
    39         for(int l = 0; l<=n; l++)
    40             ans = max(ans, dp[l][n-l]);
    41         printf("%d
    ", ans);
    42     }
    43 }
    View Code
     
    二.逆向思维:
    1.逆向推导, 即把过程逆过来,然后就变成了:从中间开始往外取,这样就变成了连续的一段。
    2.dp[i][j]表示:区间[i, j]的最大值。
    3.枚举区间长度, 然后再枚举起点(终点就确定了)。对于dp[i][j],它可以是在dp[i+1][j]的基础上取了a[i],也可以是在dp[i][j-1]的基础上取了a[j]。两者取其大。
     
     
    代码如下:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 #define ms(a,b) memset((a),(b),sizeof((a)))
    13 using namespace std;
    14 typedef long long LL;
    15 const double EPS = 1e-8;
    16 const int INF = 2e9;
    17 const LL LNF = 2e18;
    18 const int MAXN = 2e3+10;
    19 
    20 int n;
    21 int a[MAXN], dp[MAXN][MAXN];
    22 
    23 int main()
    24 {
    25     while(scanf("%d", &n)!=EOF)
    26     {
    27         for(int i = 1; i<=n; i++)
    28             scanf("%d", &a[i]);
    29 
    30         for(int i = 1; i<=n; i++)
    31             dp[i][i] = a[i]*n;
    32 
    33         for(int len = 2; len<=n; len++)
    34         for(int i = 1; i+len-1<=n; i++)
    35         {
    36             int j = i+len-1;
    37             dp[i][j] = max(dp[i+1][j]+(n-len+1)*a[i], dp[i][j-1]+(n-len+1)*a[j]);
    38         }
    39 
    40         printf("%d
    ", dp[1][n]);
    41     }
    42 }
    View Code

    三.记忆化搜索:

    1.上面的两种方法都要考虑枚举顺序的问题,有时比较不好处理。那么可以用记忆化搜索。

    2. 思维与方法二一样,只是写法不同。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 #define ms(a,b) memset((a),(b),sizeof((a)))
    13 using namespace std;
    14 typedef long long LL;
    15 const double EPS = 1e-8;
    16 const int INF = 2e9;
    17 const LL LNF = 2e18;
    18 const int MAXN = 2e3+10;
    19 
    20 int n;
    21 int a[MAXN], dp[MAXN][MAXN];
    22 
    23 int dfs(int l, int r)
    24 {
    25     if(l==r) return n*a[l];
    26     if(dp[l][r]!=-1) return dp[l][r];
    27     int k = n-r+l;
    28 
    29     dp[l][r] = max(k*a[l]+dfs(l+1, r), k*a[r]+dfs(l,r-1));
    30     return dp[l][r];
    31 }
    32 
    33 int main()
    34 {
    35     while(scanf("%d", &n)!=EOF)
    36     {
    37         for(int i = 1; i<=n; i++)
    38             scanf("%d", &a[i]);
    39 
    40         memset(dp, -1, sizeof(dp));
    41         printf("%d
    ", dfs(1,n));
    42     }
    43 }
    View Code
  • 相关阅读:
    idea 配置mapper.xml代码提示
    vue配置请求转发解决跨域问题
    MySQL 连接出现 Authentication plugin 'caching_sha2_password' cannot be loaded
    判断链表是否有环(Java实现)
    Java实现链表反转(借助栈实现)
    IHS代理遇到404的问题
    麒峰可视化表单设计器vue版本
    2021.5.30发布内容
    表单常见问题说明
    排序算法与查找算法在项目中的实际应用
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7631257.html
Copyright © 2020-2023  润新知