石子合并全家桶

Problem - 1045 (sdnu.edu.cn)石子合并1

有n堆石子排成一行,每次选择相邻的两堆石子,将其合并为一堆,记录该次合并的得分为两堆石子个数之和。已知每堆石子的石子个数,求当所有石子合并为一堆时,最小的总得分。

第一行一个整数n(1 <= n <= 200),表示石子堆数;

第二行n个整数a(1 <= a <= 100),表示每堆石子的个数。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 210;
int f[N][N], sum[N];
int main(){
	//std::ios::sync_with_stdio(false);
    //std::cin.tie(nullptr);
	int n;
	cin >> n;
	memset(f, 0x3f, sizeof f);//初始化呢,脑子呢?!
	for (int i = 1, x; i <= n; i ++ ) {
		cin >> x;
		sum[i] = sum[i - 1] + x;
		f[i][i] = 0;
	} 	   

	for (int len = 2; len <= n; len ++ ) {
		for (int l = 1; l + len - 1 <= n; l ++ ) {
			int r = l + len - 1;
			for (int k = l; k < r; k ++ ) { // 左闭右开
				f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]); //[l,k],[k + 1,r]这都是规定
			}
			f[l][r] += sum[r] - sum[l - 1];
		}
	}
	cout << f[1][n] << '\n';
	return 0;
}

 


Problem - 1048 (sdnu.edu.cn)石子合并2

有n堆石子排成一圈,每次选择相邻的两堆石子,将其合并为一堆,记录该次合并的得分为两堆石子个数之和。已知每堆石子的石子个数,求当所有石子合并为一堆时,最小的总得分。

第一行一个整数n(1 <= n <= 200),表示石子堆数;

第二行n个整数a(1 <= a <= 100),表示每堆石子的个数,这些石子首尾相接排成一圈。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 210;
int f[N][N], sum[N], a[N];
int main(){
	//std::ios::sync_with_stdio(false);
    //std::cin.tie(nullptr);
	int n;
	cin >> n;
	memset(f, 0x3f, sizeof f);
	for (int i = 1; i <= n; i ++ ) {
		cin >> a[i];
		sum[i] = sum[i - 1] + a[i];
		f[i][i] = 0;
	} 	  
// 还是要求前缀和,查询区间和为多少
	for (int i = n + 1; i <= 2 * n; i ++ ) {
		f[i][i] = 0;
		sum[i] = sum[i - 1] + a[i % n];
	}
	for (int len = 2; len <= n; len ++ ) {
		for (int l = 1; l + len - 1 <= 2 * n; l ++ ) {
			int r = l + len - 1;
			for (int k = l; k < r; k ++ ) {
				f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]);
			}
			f[l][r] += sum[r] - sum[l - 1];
		}
	}
	int ans = 0x3f3f3f3f;
	for (int i = 1; i <= n; i ++ ) {//原来是一个区间,现在变成n个区间
		ans = min(ans, f[i][i + n - 1]);
	}
	cout << ans << '\n';
	return 0;
}

Problem - 1013 (sdnu.edu.cn)1013.石子合并简化版

有n堆石子,每次从中抽取两堆进行合并,合并后的石子数记做权,并把合并后的石子堆当做新的一堆放回,重新随机抽取两堆石子,重复上面的操作,直到所有石子合并成一堆,则每次合并的和的总和是多少?

第一行:石子的堆数n(1 <= n <= 10000)。
第二行:每堆石子的石子数a[i](1 <= a[i] <= 10000)。
每次合并的权的最大总和(由于最后的结果较大,请对最终的结果mod1000000007)

贪心

每次合并两个最大的,过

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值