「SCOI2006」zh_tree

「SCOI2006」zh_tree

题目限制

  • 内存限制:250.00MB
  • 时间限制:1.00s
  • 标准输入输出

题目知识点

  • 思维
  • 动态规划 d p dp dp
    • 区间 d p dp dp

题目来源

「 洛谷 」P4539 [SCOI2006]zh_tree

题目

题目背景

张老师根据自己工作的需要,设计了一种特殊的二叉搜索树

题目描述

他把这种二叉树起名为 zh_tree,对于具有 n n n 个节点的 zh_tree,其中序遍历恰好为 ( 1 、 2 、 3 、 ⋅ ⋅ ⋅ 、 n ) (1、2、3、···、n) (123⋅⋅⋅n),其中数字 1 、 2 、 3 、 ⋅ ⋅ ⋅ 、 n 1、2、3、···、n 123⋅⋅⋅n 是每个节点的编号
n n n 个结点恰好对应于一组学术论文中出现的 n n n 个不同的单词

i i i 个单词在该组论文中出现的次数记为 d i d_i di,例如, d 2 = 10 d_2 = 10 d2=10 表示第 2 2 2 个节点所对应的单词在该组论文中出现了 10 10 10
设该组论文中出现的单词总数为 S S S,即 S = d 1 + d 2 + ⋅ ⋅ ⋅ + d n = ∑ i = 1 n d i S = d_1 + d_2 + ··· + d_n = \sum _{i = 1} ^{n} d_i S=d1+d2+⋅⋅⋅+dn=i=1ndi
f i = d i S f_i = \frac{d_i}{S} fi=Sdi 为第 i i i 个单词在该组论文中出现的 概率(频率)

张老师把根节点深度规定为 0 0 0,如果第 i i i 个节点的深度为 r i r_i ri,则访问该节点的代价为 h i h_i hi h i = k ( r i + 1 ) + c h_i = k(r_i + 1) + c hi=k(ri+1)+c,其中 k 、 c k、c kc 为已知的常数 ( 0 < k , c ≤ 100 ) (0 < k, c \leq 100) (0<k,c100)

zh_tree 是满足 h 1 f 1 + h 2 f 2 + ⋅ ⋅ ⋅ + h n f n = ∑ i = 1 n h i f i h_1f_1 + h_2f_2 + ··· + h_nf_n = \sum _{i = 1} ^ {n} h_if_i h1f1+h2f2+⋅⋅⋅+hnfn=i=1nhifi 最小的一棵二叉树
我们称上式为访问 zh_tree 的代价
请你根据已知的数据为张老师设计一棵 zh_tree

格式

输入格式

输入共 2 2 2 行:
对于第 1 1 1 行, 3 3 3 个用空格隔开的正数, n 、 k 、 c n、k、c nkc。其中 n < 30 n < 30 n<30,为整数; k 、 c k、c kc 为不超过 100 100 100 的正实数
对于第 2 2 2 行: n n n 个用空格隔开的正整数,为每个单词出现的次数 d i ( d i < 200 ) d_i(d_i < 200) di(di<200)

输出格式

输出一行:一个正实数,保留 3 3 3 位小数,表示访问 zh_tree 的最小代价

样例

样例输入

4 2 3.5
20 30 50 20

样例输出

7.000

提示

数据范围

对于 100 % 100\% 100% 的数据: 1 ≤ n < 30 1 \leq n < 30 1n<30 0 < k 、 c ≤ 100 0 < k、c \leq 100 0<kc100 d i < 200 d_i < 200 di<200


思路

对于每个节点的深度 r i r_i ri,由于 h i = k ( r i + 1 ) + c h_i = k(r_i + 1) + c hi=k(ri+1)+c,不妨可以把根节点的深度改为 1 1 1,这样就可以直接用 现在的 r i r_i ri 表示 原来的 r i + 1 r_i + 1 ri+1 了。

先把 ∑ i = 1 n h i f i \sum\limits_{i = 1}^n h_i f_i i=1nhifi 化简:
∑ i = 1 n ( h i × f i ) = ∑ i = 1 n ( k × r i + c ) × d i S = 1 S × ∑ i = 1 n ( k × r i + c ) × d i = 1 S × ∑ i = 1 n ( k × r i × d i + c × d i ) = 1 S × ( ∑ i = 1 n k × r i × d i + ∑ i = 1 n c × d i ) = ( 1 S × ∑ i = 1 n k × r i × d i ) + ( 1 S × c × ∑ i = 1 n d i ) = ( k S × ∑ i = 1 n r i × d i ) + ( 1 S × c × S ) = k × ∑ i = 1 n r i × d i S + c \begin{aligned} \sum\limits_{i = 1}^n (h_i \times f_i) & = \sum\limits_{i = 1}^n (k \times r_i + c) \times \dfrac {d_i} S \\ & = \dfrac 1 S \times \sum\limits_{i = 1} ^{n} (k \times r_i + c) \times d_i \\ & = \dfrac 1 S \times \sum\limits_{i = 1}^n (k \times r_i \times d_i + c \times d_i) \\ & = \dfrac 1 S \times (\sum\limits_{i = 1}^n k \times r_i \times d_i + \sum\limits_{i = 1}^n c \times d_i) \\ & = (\dfrac 1 S \times \sum\limits_{i = 1}^n k \times r_i \times d_i) + (\dfrac 1 S \times c \times \sum\limits_{i = 1} ^{n} d_i) \\ & = (\dfrac k S \times \sum\limits_{i = 1}^n r_i \times d_i) + (\dfrac 1 S \times c \times S) \\ & = \dfrac {k \times \sum\limits_{i = 1}^n r_i \times d_i}{S} + c \\ \end{aligned} i=1n(hi×fi)=i=1n(k×ri+c)×Sdi=S1×i=1n(k×ri+c)×di=S1×i=1n(k×ri×di+c×di)=S1×(i=1nk×ri×di+i=1nc×di)=(S1×i=1nk×ri×di)+(S1×c×i=1ndi)=(Sk×i=1nri×di)+(S1×c×S)=Sk×i=1nri×di+c

题目要我们求 ∑ i = 1 n h i f i \sum\limits_{i = 1}^n h_i f_i i=1nhifi 的最小值,就可以转化成求 ∑ i = 1 n r i × d i \sum\limits_{i = 1}^n r_i \times d_i i=1nri×di 的最小值。

  • 状态定义:设 f L , R f_{L, R} fL,R 表示:一棵二叉树的 中序遍历(左子树,根节点,右子树) L ∼ R ( L , L + 1 , L + 2 , ⋯   , R ) L \sim R(L, L + 1, L + 2, \cdots, R) LR(L,L+1,L+2,,R) ∑ i = L R r i × d i \sum\limits_{i = L}^R r_i \times d_i i=LRri×di 的最小值,最终的答案就是 k × f 1 , n S + c \dfrac{k \times f_{1, n}}{S} + c Sk×f1,n+c
  • 初始化: ∀ L = R = i , f L , R = d i \forall L = R = i, f_{L, R} = d_i L=R=i,fL,R=di ∀ L < R , f L , R = + ∞ \forall L < R, f_{L, R} = + \infty L<R,fL,R=+
  • 状态转移:对于中序遍历为 L ∼ R L \sim R LR 的二叉树,枚举其根节点 t r ( L ≤ t r ≤ R ) tr(L \leq tr \leq R) tr(LtrR) f L , R = min ⁡ t r = L R { f L , t r − 1 + f t r + 1 , R + ∑ i = L R d i } = min ⁡ t r = L R { f L , t r − 1 + f t r + 1 , R } + ∑ i = L R d i f_{L, R} = \min\limits_{tr = L}^R \{ f_{L, tr - 1} + f_{tr + 1, R} + \sum\limits_{i = L}^{R} d_i \} = \min\limits_{tr = L}^R \{ f_{L, tr - 1} + f_{tr + 1, R} \} + \sum\limits_{i = L}^{R} d_i fL,R=tr=LminR{fL,tr1+ftr+1,R+i=LRdi}=tr=LminR{fL,tr1+ftr+1,R}+i=LRdi

如果需要输出方案,可以在转移过程中记录下 f L , R f_{L, R} fL,R 取最小值时的根节点,最后递归即可。

转移时 ∑ i = L R d i \sum\limits_{i = L}^{R} d_i i=LRdi 可以用前缀和作差,这样时间复杂度 O ( n 4 ) → O ( n 3 ) O(n ^ 4) \to O(n ^ 3) O(n4)O(n3),不过都可以 AC \texttt{AC} AC


代码

#include <cstdio>
#include <cstring>

#define Min(a, b) ((a) < (b) ? (a) : (b))

const int MAXN = 30;

int N, S;
int D[MAXN + 5];
int Pre[MAXN + 5]; // 前缀和优化 

double K, C;
double dp[MAXN + 5][MAXN + 5];

int main()
{
	memset(dp, 0x3f, sizeof(dp));
	scanf("%d %lf %lf", &N, &K, &C);
	for (int i = 1; i <= N; i++)
	{
		scanf("%d", &D[i]);
		Pre[i] = S += D[i];
		dp[i][i] = 1.0 * D[i];
	}
	for (int len = 2; len <= N; len++)
	{
		for (int i = 1, j = len; j <= N; i++, j++)
		{
			dp[i][j] = Min(dp[i][j - 1], dp[i + 1][j]);
			for (int k = i + 1; k <= j - 1; k++)
				dp[i][j] = Min(dp[i][j], dp[i][k - 1] + dp[k + 1][j]);
			dp[i][j] += 1.0 * (Pre[j] - Pre[i - 1]);
		}
	}
	printf("%.3lf\n", K * dp[1][N] / S + C);
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
中描述了一个幼儿园里分配糖果的问题,每个小朋友都有自己的要求。问题的输入包括两个整数NN和KK,表示幼儿园里的小朋友数量和要满足的要求数量。接下来的KK行表示小朋友们的要求,每行有三个数字,XX,AA,BB。如果X=1,表示第AA个小朋友分到的糖果必须和第BB个小朋友分到的糖果一样多;如果X=2,表示第AA个小朋友分到的糖果必须少于第BB个小朋友分到的糖果;如果X=3,表示第AA个小朋友分到的糖果必须不少于第BB个小朋友分到的糖果;如果X=4,表示第AA个小朋友分到的糖果必须多于第BB个小朋友分到的糖果;如果X=5,表示第AA个小朋友分到的糖果必须不多于第BB个小朋友分到的糖果。这个问题可以被看作是一个差分约束系统的问题。 具体地说,可以使用差分约束系统来解决这个问题。差分约束系统是一种通过给变量之间的关系添加约束来求解最优解的方法。对于这个问题,我们需要根据小朋友们的要求建立约束条件,并通过解决这个约束系统来得出最小的糖果数量。 在问题的输入中,X的取值范围为1到5,分别对应不同的关系约束。根据这些约束,我们可以构建一个差分约束图。图中的节点表示小朋友,边表示糖果数量的关系。根据不同的X值,我们可以添加相应的边和权重。然后,我们可以使用SPFA算法(Shortest Path Faster Algorithm)来求解这个差分约束系统,找到满足所有约束的最小糖果数量。 需要注意的是,在读取输入时需要判断X和Y是否合法,即是否满足X≠Y。如果X=Y,则直接输出-1,因为这种情况下无法满足约束条件。 综上所述,为了满足每个小朋友的要求,并且满足所有的约束条件,我们可以使用差分约束系统和SPFA算法来求解这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【差分约束系统】【SCOI2011】糖果 candy](https://blog.csdn.net/jiangzh7/article/details/8872699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [P3275 [SCOI2011]糖果(差分约束板子)](https://blog.csdn.net/qq_40619297/article/details/88678605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值