第45届国际大学生程序设计竞赛(ICPC)亚洲网上区域赛模拟赛 E Eat Walnuts(区间dp)

链接:https://ac.nowcoder.com/acm/contest/8688/E
来源:牛客网

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld

题目描述

As we all know, in the ACM ICPC held in 2017, the organizer of Xinjiang University presented a box of walnuts to each coach. Our coach is happy to share with the team members except Mr.Watermelon. He is going to test Mr.Watermelon with a game when Mr.Watermelon want to eat some walnuts.

He put some walnuts in a row and let Mr.Watermelon pick one of them. And this walnut is not the first or last in the queue. The price Mr.Watermelon need to pay is : the walnut, the walnut in front of the walnut, and the walnut behind the walnut , the square of the sum of the size of these three walnuts.

For example, now there is a row of walnuts in front of Mr.Watermelon. Their size is: 3 1 50 20 15. If this time Mr.Watermelon picked the third walnut. He needs to pay (1 + 50 + 20) ∗ (1 + 50 + 20) = 5041.

After a walnut is taken away, it will leave the queue. Then Mr.Watermelon picks a walnut again until only two walnuts remain in the queue.

Mr.Watermelon wants to know what the minimum price he will pay when he takes walnuts until there are only two walnuts in the queue. But he needs more time to spend with his girlfriend. So he ask you to help him calculate this problem.

输入描述:

Input contains multiple test cases.The first line of each test case contains a integer n(3 ≤ n ≤ 100), the number of walnuts at the beginning. The second line contains n positive integers separated by spaces, representing the size of each walnut. Each positive integer does not exceed 1,000.

For 50% of the testcases, n ≤ 50.

For 90% of the testcases, n ≤ 90.

For 100% of the testcases, n ≤ 100.

The number of the testcases does not exceed 1000.

输出描述:

For each test case, print a integer–the minimum price Mr.Watermelon will pay.

示例1

输入

5
3 1 50 20 15

输出

6698

题意:

给一个数列,将除首尾以外的数删掉,每次删掉一个数a[i]的代价为(a[i - 1] + a[i] + a[i + 1])^ 2,问最小代价

思路:

区间dp,dp[i][j] 表示区间 [i, j] 的数已经删完的最小代价,第一层枚举区间长度,第二层枚举区间左端点,第三层枚举区间断点 x,转移方程:

dp[i][j] = dp[i][x - 1] + dp[x + 1][j] + (a[i - 1] + a[j + 1] + a[x])^{2}

提前赋初值:

dp[i][j] = \left\{\begin{matrix} 0, i > j\\ inf, i < j\\ (a[i - 1] + a[i] + a[i + 1])^{2},i = j \end{matrix}\right.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int N = 1e3 + 10;

int a[N], dp[N][N];

int main(){
    int n;
    while(~scanf("%d", &n)) {
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for(int i = 0; i < N; ++i)
            for(int j = i; j < N; ++j)
                dp[i][j] = inf;
        for(int i = 2; i < n; ++i) dp[i][i] = (a[i - 1] + a[i] + a[i + 1]) * (a[i - 1] + a[i] + a[i + 1]);
        for(int len = 2; len <= n - 2; ++len) {
            for(int i = 2; i + len <= n; ++i) {
                int j = i + len - 1;
                for(int x = i; x <= j; ++x) {
                    dp[i][j] = min(dp[i][j], dp[i][x - 1] + dp[x + 1][j] +
                                   (a[i - 1] + a[j + 1] + a[x]) * (a[i - 1] + a[j + 1] + a[x]));
                }
            }
        }
        printf("%d\n", dp[2][n - 1]);
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/109476594