【动态规划】之石子合并问题

这篇具有很好参考价值的文章主要介绍了【动态规划】之石子合并问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题描述

在一个操场上一排地摆放着N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请设计一个程序,计算出将N堆石子合并成一堆的最小得分和最大得分。

问题分析

我们对n的取值逐步分析

当n=1时,没有进行合并,得分为0

当n=2时,只有一种合并的方案,得分为两堆石子之和

当n=3时,有两种得分方案,先合并左边两个,先合并右边两个,这两种方案的区别我们可以看成是起点不同,最后一次合并的得分都是这三堆石子的总数

当n=4时,有三种得分方式,分别是先合并后面三个,先合并后面两个,先合并后面一个(也就是先合并前面三个),这三种方案对应的起点是1、2、3,最后一次合并的得分都是这四堆石子的总数。

由此可知,我们所求的最大或者最小的得分就是这几种方案中得分最大或者最小的分数加上最n堆石子的总石子数,可得dp方程为:

存在k属于区间[i,j]

最大得分:dp[i][j] = max(dp[i][k] +dp[k+1][j]) + sum[i][j]

最小得分:dp[i][j] = min(dp[i][k] +dp[k+1][j]) + sum[i][j]

 举例:

石子合并问题动态规划,动态规划,算法

代码实现:文章来源地址https://www.toymoban.com/news/detail-861254.html

#include <iostream>
#include <math.h>
using namespace std;

void fun(int c[],int n){
	//计算sum[][]
	int sum[100][100] = {0};
	for(int i = 0;i<n;i++){
		for(int j = 0;j<n;j++){
			if(i == j){
				sum[i][j] = c[j];
			}else if(j>i){
				sum[i][j] = c[j] + sum[i][j-1];
			}
		}
	}
	//准备两个二维数组分别用于求最大得分和最小得分 
	int dp1[100][100] = {0};
	int dp2[100][100] = {0};
	for(int len = 2;len<=n;len++){ //枚举区间 
		for(int i = 0;i < n-len+1;i++){	//枚举此区间的每一个起点,最大的起点是整排石子的长度从后面往前面减当前长度加一 
			//定义终点
			int j = i + len -1;
			dp1[i][j] = 1e8;
			dp2[i][j] = -1;
			for(int k = i;k<j;k++){	//从起点到终点一直遍历k,寻找最大最小得分· 
				dp1[i][j] = min(dp1[i][j],dp1[i][k] + dp1[k+1][j] + sum[i][j]);
				dp2[i][j] = max(dp2[i][j],dp2[i][k] + dp2[k+1][j] + sum[i][j]);
			} 
		}
	} 
	cout<<dp1[0][n-1]<<endl;
	cout<<dp2[0][n-1]<<endl;
}

int main(){
	int n;
	cin>>n;
	int c[100];
	for(int i = 0;i<n;i++){
		cin>>c[i];
	}
	fun(c,n);
	return 0;	
} 

到了这里,关于【动态规划】之石子合并问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 石子合并(动态规划 区间DP)+详细注释

    原题链接   活动 - AcWing 题目 设有 N 堆石子排成一排,其编号为 1,2,3,…,N。 每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N 堆石子合并成为一堆。 每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相

    2024年02月16日
    浏览(38)
  • C++动态规划经典案例解析之合并石子

    区间类型问题,指求一个数列中某一段区间的值,包括求和、最值等简单或复杂问题。此类问题也适用于动态规划思想。 如 前缀和 就是极简单的区间问题。如有如下数组: 现给定区间信息 [3,6] ,求区间内所有数字相加结果。即求如下图位置数字之和。 Tips: 区间至少包括

    2024年02月11日
    浏览(38)
  • 【算法设计与分析】(三)动态规划_更新中:斐波那契、二项式系数、树的最大独立集、最长递增、公共子序列、编辑距离、Hischberg、最优二叉搜索树、交替拿硬币、石子合并、背包、乘电梯

    分治 动态规划本篇 还差一堆 贪心 网络流 首先,怕误人子弟必须声明一下 本人很菜 (越复习越觉得完蛋了 作为一个科班研究生算法学成这样非常惭愧(跪 ,可能写的都不是很懂,很多内容打算背过去了。因为我发现好像真的有人看所以多提醒一句。。(大家就只食用目录

    2024年01月19日
    浏览(98)
  • 【动态规划】【C++算法】1563 石子游戏 V

    【数位dp】【动态规划】【状态压缩】【推荐】1012. 至少有 1 位重复的数字 动态规划汇总 几块石子 排成一行 ,每块石子都有一个关联值,关联值为整数,由数组 stoneValue 给出。 游戏中的每一轮:Alice 会将这行石子分成两个 非空行(即,左侧行和右侧行);Bob 负责计算每一

    2024年02月21日
    浏览(34)
  • 石子合并一章通(环形石子合并,四边形不等式,GarsiaWachs算法)(内附封面)

    在一个圆形操场的四周摆放 N N N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 2 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 试设计出一个算法,计算出将 N N N 堆石子合并成 1 1 1 堆的最小得分和最大得分。 数据的第 1 1 1 行是正

    2024年02月14日
    浏览(39)
  • 石子合并系列问题

    石子合并问题在网上有三个版本: AcWing 282. 石子合并 设有 N 堆石子排成一排,其编号为 1,2,3,…,N。 每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N 堆石子合并成为一堆。 每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆

    2024年02月02日
    浏览(58)
  • leetcode877. 石子游戏(动态规划-java)

    来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/stone-game Alice 和 Bob 用几堆石子在做游戏。一共有偶数堆石子,排成一行;每堆都有 正 整数颗石子,数目为 piles[i] 。 游戏以谁手中的石子最多来决出胜负。石子的 总数 是 奇数 ,所以没有平局。 Alice 和 Bob 轮流进行,Alic

    2024年02月10日
    浏览(57)
  • 【算法专题】动态规划之路径问题

    题目链接 - Leetcode -62.不同路径 Leetcode -62.不同路径 题目:一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示

    2024年01月24日
    浏览(48)
  • 【算法 - 动态规划】找零钱问题Ⅲ

    在前面的动态规划系列文章中,关于如何对递归进行分析的四种基本模型都介绍完了,再来回顾一下: 从左到右模型 : arr[index ...] 从 index 之前的不用考虑, 只考虑后面的该如何选择 。 范围尝试模型 :思考 [L ,R] 两端,即 开头和结尾 处分别该如何取舍。 样本对应模型 :

    2024年04月09日
    浏览(43)
  • 算法沉淀 —— 动态规划篇(路径问题)

    几乎所有的动态规划问题大致可分为以下5个步骤,后续所有问题分析都将基于此 1.、状态表示:通常状态表示分为基本分为以下两种,其中更是以第一种为甚。 以i为结尾 ,dp[i] 表示什么,通常为代求问题(具体依题目而定) 以i为开始 ,dp[i]表示什么,通常为代求问题(具

    2024年04月17日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包