首页 > 其他分享 >AcWing 282. 石子合并

AcWing 282. 石子合并

时间:2023-12-04 15:13:11浏览次数:40  
标签:int 石子 合并 len 282 AcWing

题面:
设有 \(N\) 堆石子排成一排,其编号为 \(1,2,3,…,N\),现在要将这 \(N\) 堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和。请找出一种合理的方法,使总的代价最小,输出最小代价。

原题链接:282. 石子合并 - AcWing

乍一看上去很像哈夫曼树,但并不是,因为只能合并相邻的两堆。
必须相邻也成为了该题的关键,即最后一次合并的一定是连续的两堆

区间DP

  • 状态表示:所有将 \([i,j]\) 合并为一堆的方案集合属性为最小值 \(min\) 。
  • 状态计算
    • 分界点 \(k\) 的选择:在 \(i\) 到 \(j\) 区间内可以取 \(i,i+1,i+2,...j-1\);
    • 状态转移方程:\(f[i][j]=min(f[i][j],f[i][k],f[k+1][j]+s[j]-s[i-1])\)
  • 区间DP常用模版[1]长度+左端点
    • 第一维通常是枚举区间长度,并且一般 \(len = 1\) 时进行初始化,枚举从 \(len = 2\) 开始;
    • 第二维枚举起点 \(i\) (右端点 \(j\) 自动获得,\(j = i + len - 1\))
#include <bits/stdc++.h>
using namespace std;

const int N = 310;
int n;
int s[N];	//前缀和
int f[N][N];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i];
		s[i] += s[i - 1];
	}
	//枚举区间长度len,若len=1,则不需要付出合并代价
	for (int len = 2; len <= n; len++) {
	    //枚举起点i,从i开始的len长度区间不能超过n
		for (int i = 1; i + len - 1 <= n; i++) {
			int j = i + len - 1;    //终点j
			f[i][j] = 1e8;
			//枚举分界点k,范围为[i,j-1]
			for (int k = i; k < j; k++)
			    //s[j]-s[i-1] 代表合并[i,k] [k+1,j] 这两堆石子的代价
				f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + s[j] - s[i - 1]);
		}
	}
	cout << f[1][n];
}

  1. AcWing 282. 石子合并(区间 DP 模版题详解分析) - shwei ↩︎

标签:int,石子,合并,len,282,AcWing
From: https://www.cnblogs.com/haruhomu/p/17874984.html

相关文章

  • Acwing 3240. 压缩编码
    本题大意:使用01串为单词编码,要求:1、编码使用前缀码,即任何一个单词的编码不是另一个单词编码的前缀;2、编码需要按字典序升序排列,比如 \(C\) 的编码的字典序需要 \(D\) 的编码之前。请找出一种字典序编码,使得文字经过编码后的长度\(L\)最小,输出最小长度。原题链接:324......
  • AcWing 143. 最大异或对
    题面:在给定的\(N\)个整数\(A1,A2……AN\)中选出两个进行\(xor\)(异或)运算,得到的结果最大是多少?原题链接:143.最大异或对-AcWing什么是异或?1、相同为\(0\),不同为\(1\);2、\(0\)和任意数字进行异或,结果为数字本身。为什么该题采用二叉字典树?整数可以转化为32位......
  • AcWing 835. Trie字符串统计
    题面:维护一个字符串集合,支持两种操作:①Ix向集合中插入一个字符串x;②Qx询问一个字符串在集合中出现了多少次。共有\(N\)个操作,所有输入的字符串总长度不超过\(105\),字符串仅包含小写英文字母。原题链接:835.Trie字符串统计-AcWingTrie字典树[1]//输入:Idog......
  • AcWing 831. KMP字符串
    题面:给定一个字符串S,以及一个模式串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串P在字符串S中多次作为子串出现。求出模式串P在字符串S中所有出现的位置的起始下标。原题链接:831.KMP字符串-AcWing核心:next数组-最长相等前后缀next[i]存储......
  • AcWing 92. 递归实现指数型枚举
    题面:从\(1∼n\)这\(n\)个整数中随机选取任意多个,输出所有可能的选择方案(求子集)。原题链接:92.递归实现指数型枚举-AcWing目录:使用dfs树的解法使用二进制与状态压缩的解法1.使用dfs树的解法层级既代表递归深度也代表当前数字,左子树为选该层数字,右子树为不选。#i......
  • AcWing 842. 排列数字 && AcWing 843. n-皇后问题
    842.排列数字(全排列)题面:给定一个整数\(n\),将数字\(1∼n\)排成一排,将会有很多种排列方法。现在,请你按照字典序将所有的排列方法输出。#include<iostream>usingnamespacestd;constintN=10;intpath[N];//保存序列boolst[N];//数字是否被用过,bool类型的全局变......
  • AcWing 828. 模拟栈
    题面:实现一个栈,栈初始为空,支持四种操作:pushx–向栈顶插入一个数\(x\);pop–从栈顶弹出一个数;empty–判断栈是否为空;query–查询栈顶元素。现在要对栈进行\(M\)个操作,其中的每个操作\(3\)和操作\(4\)都要输出相应的结果。原题链接:828.模拟栈-AcWing//......
  • AcWing 3302. 表达式求值
    题面:给定一个表达式,其中运算符仅包含加减乘除,可能包含括号,请你求出表达式的最终值。原题链接:3302.表达式求值-AcWing基本思路创建两个栈,分别存储数字和运算符运算符的判定:仅在以下条件满足时将运算符直接压入栈中:①栈中不存在元素②当前运算符优先级比栈顶高③栈顶为......
  • AcWing 154. 滑动窗口
    题面:给定一个大小为\(n≤10^6\)的数组。有一个大小为\(k\)的滑动窗口,它从数组的最左边移动到最右边。你只能在窗口中看到\(k\)个数字。每次滑动窗口向右移动一个位置。你的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。原题链接:154.滑动窗口-AcWing......
  • AcWing 785. 快速排序
    题面:给定你一个长度为\(n\)的整数数列。请你使用快速排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。原题链接:785.快速排序-AcWing需要注意的几个点:左右哨兵的发动顺序;相同元素的相对位置;边界划分问题[1]。#include<bits/stdc++.h>usingna......