二叉树问题

时间限制: 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. JS判断当前手机类型

    window.onload = function () { var u = navigator.userAgent; if (u.indexOf('Android') > -1 || u.ind ...

  2. 第三章 霍夫变换(Hough Transform)

    主要内容: 霍夫变换的作用 霍夫变换检测直线的原理 霍夫变换检测圆的原理 OpenCV中的霍夫变换 1.霍夫变换检测直线原理 霍夫变换,英文名称Hough Transform,作用是用来检测图像中的直 ...

  3. c# 对加密的MP4文件进行解密

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  4. Linux C 程序的开发环境

    1.开发环境的构成 编辑器 vim,vi 编译器 gcc 调试器 gdb 函数库glibc 系统头文件glibc_header 2.gcc编译器 功能强大.性能优越的多平台编译器,gcc可以将c.c+ ...

  5. java swing 添加 jcheckbox复选框

    总体上而言,Java Swing编程有两大特点:麻烦.效果差. 麻烦是说由于设计器的使用不方便(如果您希望使用窗体设计器通过快速拖拽控件建立您的Java Swing GUI程序,请您使用MyEclip ...

  6. html学习笔记 - table表格

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

  7. elasticsearch系列(四)部署

    本文采用tar包的方式部署es 准备jdk8的环境 5.4.0的es依赖jdk8及以上版本 下载linux版的jdk jdk-8u121-linux-x64.tar.gz tar -zvxf jdk- ...

  8. Dockerfile 最佳实践

    之前 一篇文章介绍 docker 的镜像基本原理和概念 ,主要介绍在编写 docker 镜像的时候一些需要注意的事项和推荐的做法. 虽然 Dockerfile 简化了镜像构建的过程,并且把这个过程可以 ...

  9. GoodReads: Machine Learning (Part 3)

    In the first installment of this series, we scraped reviews from Goodreads. In thesecond one, we per ...

  10. OWIN 自宿主模式WebApi项目,WebApi层作为单独类库供OWIN调用

    OWIN是Open Web Server Interface for .NET的首字母缩写,他的定义如下: OWIN在.NET Web Servers与Web Application之间定义了一套标准 ...