[ifrog 1066 - Buy Candy] 四边形优化的石子合并

[ifrog 1066 - Buy Candy] 四边形优化的石子合并

1. 题目链接

[ifrog 1066 - Buy Candy]

2. 题意描述

给定 N 组人,现在需要将这N组人合并为 1 组人。每次只能合并相邻的两组人,且合并的代价为f(t) t 表示的是两组人数之和,函数f(x)的表示如下:

f(x)=i=0m(aixi);ai

求合并的最小代价。 (1n1000,1m4)

3. 解题思路

首先,如果不知道“石子合并”或者“四边形优化”的可以点击下面的链接进行学习。

  1. [ACdreamers 石子合并问题]
  2. [百度百科 四边形不等式]

然后,我们可以很容易写出DP方程,如下:

dp[i][j]=min{dp[i][k]+dp[k+1][j]+sum[i,j]};

sum[i,j][i,j]

最后,用四边形不等式优化一下。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int MAXN = 1000 + 5;
const int INF = 0x3f3f3f3f;

int n, m, s[MAXN], a[MAXN];
int p[MAXN][MAXN], sum[MAXN];
LL dp[MAXN][MAXN];

LL calc(int x) {
    LL ret = 0, z = 1;
    for(int i = 0; i <= m; i++) {
        ret += a[i] * z;
        z *= x;
    }
    return ret;
}

int main() {
#ifndef ONLINE_JUDGE
//    freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int _;
    scanf("%d", &_);
    while(_ --) {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &s[i]);
        scanf("%d", &m);
        for(int i = 0; i <= m; i++) scanf("%d", &a[i]);
        memset(dp, 0x3f, sizeof(dp));

        sum[0] = 0;
        for(int i = 1; i <= n; i++) {
            dp[i][i] = 0;
            p[i][i] = i;
            sum[i] = sum[i - 1] + s[i];
        }

        for(int len = 2; len <= n; len++) {
            for(int i = 1; i + len - 1 <= n; i++) {
                int j = i + len - 1;
                for(int k = p[i][j - 1]; k <= p[i + 1][j]; k++) {
                    LL val = dp[i][k] + dp[k + 1][j] + calc(sum[j] - sum[i - 1]);
                    if(val < dp[i][j]) {
                        dp[i][j]= val;
                        p[i][j] = k;
                    }
                }
            }
        }
        printf("%lld\n", dp[1][n]);
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值