Luo Gu P2858 cows snack solution to a problem zone DP entry title

Subject to the effect:

John often made special allowances for high milk yield of cows, and soon the cows have large sums of money I do not know how to spend. For this reason, John purchased a \ (N (1 \ le N \ le 2000) \) parts of delicious snacks to sell the cows. John sold a daily snack. John certainly hope after all these snacks sold to get the maximum benefit. These snacks have following interesting features:

  • Snacks according to \ (1 \ cdots N \) numbers, which are in a row in a long box. The box has openings at both ends, John outermost one may be removed from either end of the box per day.
  • Similar to wine and delicious cheese, the longer these snacks store more delicious. Of course, so John can sell them a higher price.
  • The initial value of each snack is not necessarily the same. When John the purchase, the \ (i \) initial value as part of snacks \ (V_i (1 \ Le V_i \ Le 1000) \) .
  • The first \ (I \) parts of the snack after being if buy \ (A \) days sold, its price is \ (V_i \ Times A \) .

\ (V_i \) is down from the top of the box parts of the initial value of i snacks. John told the initial value of all your snacks, and hope you can help him calculate, after these snacks all been sold, how much he can get the most money.

Problem-solving ideas:

We define the state \ (f [L] [R ] \) is the interval \ ([L, R] \ ) followed by an empty can to be able to get the most money.

Then we can find our answer is \ (f [1] [n ] \) , then how to solve the \ (f [1] [n ] \) it? To not worry, listen to me carefully to have ~

Suppose we now require solution \ (f [L] [R] \) , then we can find, for the interval \ ([L, R] \) , we take away a snack of only two solutions:

  • A scheme: removed from the left \ (V_L \) , then the state becomes \ (F [. 1 + L] [R & lt] \) ;
  • Option II: is removed from the right side of \ (V_R \) , then the state becomes \ (F [L] [R & lt-. 1] \) .

For the interval \ ([L, R] \) , Let's make sure we take away snacks (whether it is a program or Option II) is first removed several snacks?

We can see, \ ([L, R & lt] \) left section are \ (L-1 \) parts of the snack is removed prior to, right is \ (nR \) parts snack before being removed, so we now take the snacks are \ (L-1 + nR + 1 = n + LR \) parts.

Therefore, using the most money first option is to obtain

\[f[L+1][R] + V_l \times (n+L-R)\]

The second option uses the most money can be obtained

\[f[L][R-1] + V_R \times (n+L-R)\]

We require that the state now Solutions \ (f [L] [R ] \) should be the larger value of the two schemes, we can obtain the final state transition equation is as follows:

\[f[L][R] = \max(f[L+1][R] + V_l \times (n+L-R), f[L][R-1] + V_R \times (n+L-R))\]

Of course, also be noted that our case boundary conditions, namely: the length of the interval \ (1 \) the case when, at this time, the interval for all \ ([I, I] \) , the first \ (I \) snacks parts are removed in the final (i.e. \ (n-\) parts is removed), so

\[f[i][i] = V_i \times n\]

Based on the above derivation, we can achieve our main memory of the code in the form of search:

int dfs(int L, int R) {
    if (f[L][R])    // 记忆化操作
        return f[L][R];
    if (L == R)     // 边界条件
        return V[L] * n;
    return f[L][R] = max(dfs(L+1, R)+V[L]*(n+L-R), dfs(L, R-1)+V[R]*(n+L-R));
}

Thinking and memory search is still very correspond to our way of thinking human brain, we can see that this program is divided into three parts:

Our first dfs(L,R)is to return \ (f [L] [R] \) , so it:

  • First, judgment is not already the calculated (by \ (f [L] [R ] \) whether \ (0 \) is determined), has been calculated directly if the result of play;
  • Secondly, the boundary condition is not determined (by \ (L \) is equal to \ (R & lt \) to determine) if the boundary condition is returned directly \ (V_L \ n-Times \) ;
  • Finally, the value calculated and recorded, so that the next time is calculated directly returned.

Use Memory search complete code is as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int n, V[maxn], f[maxn][maxn];
int dfs(int L, int R) {
    if (f[L][R])    // 记忆化操作
        return f[L][R];
    if (L == R)     // 边界条件
        return V[L] * n;
    return f[L][R] = max(dfs(L+1, R)+V[L]*(n+L-R), dfs(L, R-1)+V[R]*(n+L-R));
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> V[i];
    cout << dfs(1, n) << endl;
    return 0;
}

We can also adopt a general form to solve this problem (usually in the form of search and memory in the form of the idea is the same, but one is coming down the straight for loop, the other is the recursive come, and to distinguish between analogy).

We can find a large interval (i.e., interval length larger section) is through the state corresponding to the inter-cell (i.e., a smaller interval length interval) corresponding to the derived state, so long as we traverse the interval length from small to large, then left coordinate traversing interval, to calculate the corresponding state.
The main code is as follows:

for (int l = 1; l <= n; l ++) { // 从小到大遍历区间长度l
    for (int i = 1; i+l-1 <= n; i ++) { // 遍历区间左边界i
        int j = i+l-1;  // 通过左边界i和区间长度l获得区间右边界j
        if (l == 1) f[i][j] = V[i]*n;   // 边界条件直接返回结果
        else f[i][j] = max(f[i+1][j] + V[i]*(n+i-j), f[i][j-1] + V[j]*(n+i-j)); // 否则,通过状态转移方程推导
    }
}

The general form of the complete codes are as follows:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int n, V[maxn], f[maxn][maxn];
int main() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> V[i];
    for (int l = 1; l <= n; l ++) { // 从小到大遍历区间长度l
        for (int i = 1; i+l-1 <= n; i ++) { // 遍历区间左边界i
            int j = i+l-1;  // 通过左边界i和区间长度l获得区间右边界j
            if (l == 1) f[i][j] = V[i]*n;   // 边界条件直接返回结果
            else f[i][j] = max(f[i+1][j] + V[i]*(n+i-j), f[i][j-1] + V[j]*(n+i-j)); // 否则,通过状态转移方程推导
        }
    }
    cout << f[1][n] << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/quanjun/p/12153813.html