51nod-1021 石子归并

基准时间限制:1 秒 空间限制:131072 KB 分值: 20  难度:3级算法题
 收藏
 关注
N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。

例如: 1 2 3 4,有不少合并方法
1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)
1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)
1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)

括号里面为总代价可以看出,第一种方法的代价最低,现在给出n堆石子的数量,计算最小合并代价。
Input
第1行:N(2 <= N <= 100)
第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)
Output
输出最小合并代价
Input示例
4
1
2
3
4
Output示例
19

题解:第一次知道四边形优化。。具体证明点击打开链接

知道了四边形优化后就是水题了。不过因为是环,所以要特殊处理一下。环的情况即以数组任意一个元素为开头枚举即可。但这样会T(n^3)故我们将长度为n的数组变成长度为2 * n的数组,每次处理时最多处理n个连续元素,复杂度较直线石子合并只多了常数乘项(4)

AC代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
typedef long long ll;

using namespace std;

const ll maxn = 2e3 + 5, inf = 1e18 + 10;
ll sum[maxn], dp[maxn][maxn], s[maxn][maxn];

void init(){
	memset(dp, 0, sizeof(dp));
	memset(s, 0, sizeof(s));
	memset(sum, 0, sizeof(sum));
	for(int i = 1; i < maxn; i++){
		s[i][i] = i;
		for(int j = 1; j < maxn; j++)
			dp[i][j] = inf;
		dp[i][i] = 0;
	}
}

int main(){
	init();
	ll n, t;
	
	scanf("%lld", &n);
	for(ll i = 1; i <= n; i++){
		scanf("%lld", &t);
		sum[i] = sum[i - 1] + t;
	}
	for(ll i = 1; i <= n; i++)
		sum[i + n] = sum[n] + sum[i];
	
	for(ll i = 2 * n; i >= 1; i--){
		t = min(2 * n, i + n - 1);
		for(ll j = i + 1; j <= t; j++){
			for(ll k = s[i][j - 1]; k <= s[i + 1][j]; k++){
				if(dp[i][j] > dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]){
					s[i][j] = k;
					dp[i][j] = dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1];
				}
			}
		}
	}
	ll ans = dp[1][n];
	for(ll i = 2; i <= n; i++)
		ans = min(ans, dp[i][i + n - 1]);
	printf("%lld\n", ans);
	return 0;
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值