二叉树问题

时间限制: 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. shop_list

    #!/usr/bin/env python # -*- coding: utf-8 -*- #输出商品列表,用户输入序号,显示用户选中的商品 li = ["手机", "电 ...

  2. PRML读书笔记——机器学习导论

    什么是模式识别(Pattern Recognition)? 按照Bishop的定义,模式识别就是用机器学习的算法从数据中挖掘出有用的pattern. 人们很早就开始学习如何从大量的数据中发现隐藏在背后 ...

  3. Android自定义评分控件:RatingStarView

    RatingStarView Android自定义的评分控件,类似ProgressBar那样的,使用星星图标(full.half.empty)作为progress标识的评分/打分控件. 效果图 图1: ...

  4. 【iOS开发】3.UIViewController

    1.概述 iOS和相关库的开发大量使用了模型-视图-控制器(MVC)模式.一般而言,MVC是一种策略,用于分离展现(视图).数据(模型)和业务逻辑(控制器).确切地讲,模型是简单数据,如Person或 ...

  5. php 中时间函数date及常用的时间计算

    曾在项目中需要使用到今天,昨天,本周,本月,本季度,今年,上周上月,上季度等等时间戳,趁最近时间比较充足,因此计划对php的相关时间知识点进行总结学习 1,阅读php手册date函数 常用时间函数: ...

  6. 接上一篇中记录Echarts进度环使用【不同状态不同进度环颜色及圈内文字】--采用单实例业务进行说明

    接上一篇中记录Echarts进度环使用 此处处理不同状态下不同进度环颜色及圈内文字等的相关处理,采用实际案例源码说明 -----------------偶是华丽丽分割线---------------- ...

  7. 通过vmware 启动cloudera-quickstart-vm-5.10.0-0-vmware.zip镜像无法启动。

    解压cloudera-quickstart-vm-5.10.0-0-vmware.zip中找到cloudera-quickstart-vm-5.10.0-0-vmware.vmx文件打开注释点#msg ...

  8. Python3.5 在Ubuntu16.04上无法画图的解决方案

    1. 问题由来 在使用下面的测试代码学习python时,用Pycharm画不出来图像,SPYDER3 可以画出来. 下面的代码来自:http://old.sebug.net/ # -*- coding ...

  9. Ubuntu安装Cassandra

    Uninstall Cassandra $ sudo su remove cassandra $ apt-get remove cassandra cleaned the cassandra fold ...

  10. ke

    #include <stdio.h> #include <stdlib.h> // For rand() and srand() #include <time.h> ...