二叉树问题

时间限制: 1 Sec  内存限制: 128 MB

题目描述

Petya Bulochkin很幸运:他得到了一份在“Macrohard”公司的工作。他想要展现他的才华,所以他要把他第一份工作做得尽可能好。这个任务是写一个搜索引擎。Petya知道一系列的整数A1,A2,……,Ak(k<=300, 1<=Ai<=10000000, Ai 都不相同)我们把这些数称作关键字。这个引擎应该要能回答这样的问题:“那里是不是有一个关键字是S?”我们已经知道,S是1到n(1<=n<=10000000)中任何一个整数。Petya决定使用排序二叉树来解决这个问题。
我们把比较的次数称作费用C。例如,对于第三棵二叉树,我们有对于每一个S的查找费用:
S 1 2 3 4 5 6 7 8 9 10 11
C 2 3 3 3 3 3 1 2 2 2 2
我们把对于s=1~n的费用和称作二叉树的费用,例如,第三棵二叉树的费用是2+3+3+3+3+3+1+2+2+2+2=26
我们的任务是对于关键字A1~Ak,写出由这些关键字形成的二叉树中的最小费用。

输入

第一行是n,第二行是k,下面k行中第i行是Ai

输出

输出文件仅有一行包含一个整数表示要求的最小费用。

样例输入

10
4
9
3
7
4

样例输出

22

提示

这个最小费用的二叉树指的是:
题解:
先拿样例来说,根据二叉搜索树的左小右大的性质,4~7都是查找2次,7~9都是查找3次,不难发现,查找次数相同的数都是以区间的形式存在的。
因此判断这道题是区间DP,将n个数从小到大排序即可。
确定了思路,现在让我们来看怎么定义状态,定义状态是这道题的难点,本人一开始简单的认为f[i][j]表示在区间i~j中查找数a[i]~a[j]的最小次数,发现后效性不可避免。后来听了点大佬的教导,其实正确的状态定义应该为f[i][j]表示在区间i~j中查找a[i-1]+1~a[j+1]-1的最小次数。(是不是很巧妙?)
动规方程很简单f[j][i+j-1]=min(f[j][i+j-1],f[j][k-1]+(a[i+j]-a[j-1]-1));
AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
using namespace std;
int n,m;
int a[],f[][];
int main()
{
int i,j,k;
memset(f,/,sizeof(f));
scanf("%d",&m);
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
sort(a+,a+n+);
a[]=;a[n+]=m+;
for(i=;i<=n;i++)
f[i][i]=a[i+]-a[i-]-;
for(i=;i<=n;i++)
{
for(j=;j<=n-i+;j++)
{
for(k=j;k<=i+j-;k++)
{
if(k==j)f[j][i+j-]=min(f[j][i+j-],f[k+][i+j-]+(a[i+j]-a[j-]-));
else if(k==i+j-)f[j][i+j-]=min(f[j][i+j-],f[j][k-]+(a[i+j]-a[j-]-));
else f[j][i+j-]=min(f[j][i+j-],f[j][k-]+f[k+][i+j-]+(a[i+j]-a[j-]-));
}
}
}
cout<<f[][n];
return ;
}

特别感谢,@SilverWolf

二叉树问题(区间DP好题)的更多相关文章

  1. 又一道区间DP的题 -- P3146 [USACO16OPEN]248

    https://www.luogu.org/problemnew/show/P3146 一道区间dp的题,以区间长度为阶段; 但由于要处理相邻的问题,就变得有点麻烦; 最开始想了一个我知道有漏洞的方程 ...

  2. poj 2955 Brackets (区间dp基础题)

    We give the following inductive definition of a “regular brackets” sequence: the empty sequence is a ...

  3. 状态压缩---区间dp第一题

    标签: ACM 题目 Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is ...

  4. poj 2955 区间dp入门题

    第一道自己做出来的区间dp题,兴奋ing,虽然说这题并不难. 从后向前考虑: 状态转移方程:dp[i][j]=dp[i+1][j](i<=j<len); dp[i][j]=Max(dp[i ...

  5. codeforces 1140D(区间dp/思维题)

    D. Minimum Triangulation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  6. 区间dp板子题:[noi1995]石子合并

    非常经典的区间dp模板 对于每一个大于二的区间 我们显然都可以将它拆分成两个子序列 那么分别计算对于每个取最优值即可 #pragma GCC optimize("O2") #inc ...

  7. zoj3469 区间dp好题

    /* 按坐标排序 以餐厅为起点向两边扩展区间 dp[i][j][0]表示送完区间[i,j]的饭后停留在左边的代价 dp[i][j][1]表示送完区间[i,j]的饭后停留在右边的代价 */ #inclu ...

  8. [nyoj737]石子归并(区间dp入门题)

    题意:有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值 ...

  9. 【Luogu】P1040加分二叉树(区间DP)

    题目链接 区间DP,因为中序遍历的性质:区间[l,r]的任何一个数都可以是该区间的根节点. 更新权值的时候记录区间的根节点,最后DFS输出. 见代码. #include<cstdio> # ...

随机推荐

  1. OC 动态类型和静态类型

    多态 允许不同的类定义相同的方法 动态类型 程序直到执行时才能确定所属的类 静态类型 将一个变量定义为特定类的对象时,使用的是静态形态 将一个变量定义为特定类的对象时,使用的是静态类型,在编译的时候就 ...

  2. 简单的3D图片轮播dome

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. bootstrap 获得轮播中的索引或当前活动的焦点对象

    今天用bootstrap做一个轮播,当轮播滚到每张图的时候,在页面下面就显示相对应的内容,那么问题来了:为了轮播图的可扩展性,我们肯定需要知道当前活动(显示图片)的索引号,查了bootstrap文档, ...

  4. NancyFx 2.0的开源框架的使用-Forms

    同样的像前面2篇博文一样,每个项目的开始基本都是建个空的Web项目 在NuGet库中安装以下几个NuGet包 Nancy Nancy.Authentication.Forms Nancy.Hostin ...

  5. Redis学习-SortedSet

    Sorted-Sets和Sets类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中.它们之间的主要差别是Sorted-Sets中的每一个成员都会有一个分数(score)与之关联, ...

  6. Hibernate 核心接口和工作机制

    主要内容 Configuration类 sessionFactory接口 session接口 Transaction接口 Query 和 criteria接口 1.Configuration类 负责管 ...

  7. Windows 2008 R2下 如何简单使用IIS来配置PHP网站

    虽然PHP网站配置一般大多数人可能会联想到用Apache+php+mysql来配置,但是呢,如果是为了安全性考虑或者是说是为了便捷高效快速的完成工作,那么Apache+php+mysql这个配置工作就 ...

  8. React入门---基础知识-大纲-1

    -----------------在慕课网学习react入门笔记-------------- ---------博主边学边记录,手把手进行学习及记录---------- --------------- ...

  9. Day5模块-os和sys模块

    os模块:操作系统调用的接口 ------------------------------------------------------------------------------------- ...

  10. 如何创建并运行java线程

    本文转载地址:            http://ifeve.com/creating-and-starting-java-threads/ Java线程类也是一个object类,它的实例都继承自j ...