付费下载
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、树型动态规划的实例分析一、树型动态规划顾名思义,树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向:1 根叶:不过这种动态规划在实际中运用的不多,也没有比较明显的例题,所以不在今天的范围之内。2 叶根:既根的子节点传递有用的信息给根,完后根得出最优解的过程。这类的习题比较的多,下面就介绍一些这类题目和它们的一般解法。二、例题与加分二叉树【问题描述】设一个n 个节点的二叉树 tree 的中序遍历为(l,2,3,n),其中
2、数字 1,2,3,n 为节点编号。每个节点都有一个分数(均为正整数),记第 i 个节点的分数为 di,tree 及它的每个子树都有一个加分,任一棵 subtree(也包含 tree 本身)的加分计算方法如下:subtree 的树的加分 subtree 的右的加分subtree 的根的分数若某个。为空,规定其加分为 1,叶子的加分就是叶节点本身的分数。不考虑它的空试求一棵符合中序遍历为(1,2,3,n)且加分最高的二叉树 tree。要求输出;tree 的最高加分tree 的前序遍历【输入格式】第 1 行:一个整数 n(n30),为节点个数。第 2 行:n 个用空格隔开的整数,为每个节点的分数(分
3、数100)。【输出格式】第 1 行:一个整数,为最高加分(结果不会超过 4,000,000,000)。第 2 行:n 个用空格隔开的整数,为该树的前序遍历。【输入样例】55 7 1 2 10【输出样例】1453 1 2 4 5分析很显然,本题适合用动态规划来解。如果用数组 valuei,j表示从节点 i 到节点 j 所组成的二叉树的最大加分,则动态方程可以表示如下: valuei,j=maxvaluei,i+valuei+1,j,valuei+1,i+1+valuei,i*valuei+2,j,valuei+2,i+2+valuei,i+1*valuei+3,j,valuej-1,j-1+va
4、luei,j-2*valuej,j,valuej,j+valuei,j-1题目还要求输出最大加分树的前序遍历序列,因此必须在计算过程中记下从节点 i 到节点 j所组成的最大加分二叉树的根节点,用数组 rooti,j表示PASCAL 源程序$N+program NOIP2003_3_Tree; constmaxn=30; vari,j,n,d:byte; a:array1.maxnof byte;value:array1.maxn,1.maxnof comp; root:array1.maxn,1.maxnof byte;p;f1,f2:text;fn1,fn2,fileNo:string;pr
5、ocedure preordbegin1,p2:byte);按前序遍历输出最大加分二叉树if p2=p1 then beginwrite(f2,rootp1,p2, );preord1,rootp1,p2-1);preorder(rootp1,p2+1,p2); end;end; beginwrite(Input fileNo:);readln(fileNo); fn1:=tree.in+fileNo;fn2:=tree.ou+fileNo; assign(f1,fn1);reset(f1); assign(f2,fn2);rewrite(f2);readln(f1,n);for i:=1 t
6、o n do read(f1,ai); close(f1); fillchar(value,sizeof(value),0);for i:=1 to n do beginvaluei,i:=ai;计算单个节点的二叉树的加分的二叉树的根节点rooti,i:=i;end;单个节点for i:=1 to n-1 do beginvaluei,i+1:=ai+ai+1;计算相邻两个节点的二叉树的最大加分rooti,i+1:=i;相邻两个节点的二叉树的根节点;需明的是,两个节点构成的二叉树,其根节点可以是其中的任何一个;这里选小的为根节点,则大的为其右;若选大的为根节点,则小的为其树;因此,最后输出的前
7、序遍历结果会有部分不同,但同样是正确的。如果最大加分二叉树的所有节点的度数都是 0 或 2,则最后输出的前序遍历结果是唯一的。end;for d:=2 to n-1 do begin依次计算间距为 d 的两个节点for i:=1 to n-d do begin的二叉树的最大加分s:=valuei,i+valuei+1,i+d;计算以 i 为根节点,以 i+1 至 i+d 间所有节点为右的二叉树的最大加分rooti,i+d:=i; 根节点 ifor j:=1 to d do begintemp:=valuei+j,i+j+valuei,i+j-1*valuei+j+1,i+d;计算以 i+j 为
8、根节点,以 i 至i+j-1 间所有节点为树,以 i+j+1 至 i+d 间所有节点为右的二叉树的最大加分if temps then begin如果此值为最大 s:=temp;rooti,i+d:=i+j;记下新的最大值和新的根节点end; end;temp:=valuei,i+d-1+valuei+d,i+d;计算以 i+d 为根节点,以 i 至 i+d-1 间所有节点为树的二叉树的最大加分 if temps then begins:=temp;rooti,i+d:=i+d+1; end;valuei,i+d:=s; end;end;wrin(f2,value1,n:0:0);输出最大加分
9、preorder(1,n);输出最大加分二叉树的前序遍历序列 close(f2);end.点评基本题。考查了二叉树的遍历和动态规划算法。难点在于要的根节点。疑点是最大加分二叉树的前序遍历序列可能不唯一。当前最大加分二叉树Ps:其实这题真正意义上来说还是一道普通的 dp 题目,但它批上了树的外表,所以都拿来作对比和。Ural 1018二*苹果树题目有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点)这棵树共有N 个结点(叶子点或者树枝分叉点),为 1-N,树根一定是 1。用一根树枝两端连接的结点的来描述一根树枝的位置。下面是一颗有 4 个树枝的树25 / 34 /
10、1现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。给定需要保留的树枝数量,求出最多能留住多少苹果。输入格式第 1 行 2 个数,N 和 Q(1=Q= N,1N=100)。N 表示树的结点数,Q 表示要保留的树枝数量。接下来 N-1 行描述树枝的信息。每行 3 个整数,前两个是它连接的结点的每根树枝上的苹果不超过 30000 个。第 3 个数是这根树枝上苹果的数量。输出格式一个数,最多能留住的苹果的数量。样例输入5 23 5 20样例输出21:因为题目一给出就是二叉的,所以很容易就可以写出方程:a(I,j):=max(a(i.left,k)+a(i.right,j-k),0=kj the
11、n j:=k;end; treedp:=j;End;选课问题描述在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程 a 是课程b 的先修课即只有学完了课程 a,才能学习课程 b)。一个学生要从这些课程里选择 M 门课程学习,问他能获得的最大学分是多少?输入:第一行有两个整数 N,M 用空格隔开。(1=N=200,1=M=150)接下来的 N 行,第 I+1 行包含两个整数 ki 和 si, ki 表示第 I 门课的直接先修课,si 表示
12、第 I门课的学分。若 ki=0 表示没有直接先修课(1=ki=N, 1=si=0 then exit; treedp(ax.r,y);只有右j:=bax.r,y;for k:=1 to y do左右 begintreedp(ax.l,k-1);treedp(ax.r,y-k););的情况都有的情况i:=bax.l,k-1+bax.r,y-k+ax.k; if ij then j:=i;end; bx,y:=j;end;begin readln(s);assign(input,s);reset(input); readln(n,m); fillchar(f,sizeof(f),0);for i:
13、=0 to n dobegin ai.l:=-1;ai.r:=-1;ai.k:=-1;end;build tree for i:=1 to n do begin readln(k,l);ai.k:=l;if fk=0 then ak.l:=i else afk.r:=i; fk:=i;end;bianjiefor i:=-1 to n do for j:=-1 to m doif (i=-1) or (j=0) then bi,j:=0 else bi,j:=-1;tree dp treedp(a0.l,m);outputwrin(ba0.l,m); end.Tju1053 技能树Proble
14、m玩过 Diablo 的人对技能树一定是很熟悉的。一颗技能树的每个结点都是一项技能,要学会这项技能则需要耗费一定的技能点数。只有学会了某一项技能以后,才能继续学习它的后继技能。每项技能又有着不同的级别,级别越高效果越好,而技能的升级也是需要耗费技能点数的。有个玩家积攒了一定的技能点数,他想尽可能地利用这些技能点数来达到最好的效果。因此他给所有的级别都打上了分,他认为效果越好的分数也越高。现在他要你帮忙寻找一个分配技能点数的方案,使得分数总和最高。Input该题有多组测试数据。每组测试数据第一行是一个整数 n(1=n=20),表示所有不同技能的总数。接下来依次给出 n 个不同技能的详细情况。每个
15、技能描述包括 5 行。第一行是该技能的名称。第 2 行是该技能在技能树中父技能的名称,名称为 None 则表示该技能不需要任何的先修技能便能学习。第 3 行是一个整数 L(1=L=20),表示这项技能所能拥有的别。第 4 行共有L 个整数,其中第 I 个整数表示从地 I-1 级升到第 I 级所需要的技能点数(0 级表示没有学习过)。第 5 行包括L 个整数,其中第 I 个整数表示从第 I-1 级升级到第I 级的效果评分,分数不超过 20。在技能描述之后,共有两行,第 1 行是一个整数P,表示目前所拥有的技能点数。接下来 1 行是 N 个整数,依次表示角色当前习得的技能级别,0 表示还未学习。这
16、里不会出现情况。Output每组测试数据只需输出最佳分配方案所得的分数总和。Sle Input3Freezing Arrow Ice Arrow33 3 315 4 6Ice Arrow Cold Arrow 24 310 17Cold Arrow None33 3 215 5 2100 0 1Sle Output42Source浙江省 2004 组队赛第二试:这题是选课的加强版,但并难不倒还是把一棵树转换为二叉树,完后从子节点到根节点作一次 dp,最后得到最优解由于和上题很相像就不写方程了。源代码程序: program bluewater; typetree=records,sf:strin
17、g; l,r,m:long;c:array1.20 of long ; d:array1.20 of long ; end;var i,j,k,l,m,n:long;a:array0.20 of tree; b:array0.20 of long; learn:array0.20 of long;f:array0.20,0.8000 of long;function treedp(x,y:long):long; var i,j,k,l,max,o,p,q:long;beginif fx,y-1 then begreedp:=fx,y;exit;end; max:=treedp(ax.r,y);
18、learn0if learnx0 then beginfor k:=0 to y do begini:=treedp(ax.l,k)+treedp(ax.r,y-k); if imax then max:=i;end; end;learn=0 l:=0;p:=0;i:=0;for o:=1 to ax.m do beginif olearnx thenbegin l:=l+ax.co;p:=p+ax.do;end; for k:=0 to y-l dobegini:=treedp(ax.l,k)+treedp(ax.r,y-l-k)+p; if imax then max:=i;end; en
19、d;fx,y:=max; treedp:=max;end;function find(x:string):long var i,j:long;beginfor i:=0 to n doif ai.s=x then break; find:=i;end;beginwhile not(eof(input) do begininput readln(n);fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0); a0.s:=None;for i:=1 to n dowibegini doreadln(s); readln(sf); readln(m);for
20、 j:=1 to m do read(cj);readln; for j:=1 to m do read(dj);readln; end;readln(m);if m8000 then m:=8000;for i:=1 to n do read(learni);readln;build binary tree for i:=1 to n do begin k:=find(ai.sf);if bk=0 thenbegin bk:=i;ak.l:=i;endelse begin abk.r:=i;bk:=i;end; end;bian jiefor i:=0 to 20 dofor j:=0 to
21、 8000 do fi,j:=-1;for i:=0 to 8000 do f0,i:=0;mainwrin(treedp(a0.l,m); end;end.ProblemBob 喜欢玩电脑有个问题。,特别是。但是他经常无法找到快速玩过的办法。现在他他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。请你编一程序,给定一树,帮 Bob 计算出他需要放置最少的士兵.Input第一行为一整数,表示有组测试数据每组测试数据表示一棵树,描述如下:第一行 N,表示树中结点的数目
22、。第二行至第 N+1 行,每行描述每个结点信息,依次为:该结点标号 i,k(后面有 k 条边与结点 I 相连)。接下来 k 个数,分别是每条边的另一个结点标号 r1,r2,.,rk。对于一个 n(0n=1500)个结点的树,结点标号在 0 到 n-1 之间,在输入数据中每条边只出现一次。Output输出文件仅包含一个数,为所求的最少的士兵数目。例如,对于如下图所示的树:为 1(只要一个士兵在结点 1 上)。Sle Input24012353120012 330Sle Output12Sourcesgoi分析:这题有 2 种做法,一种是比较简单但不是很严密的贪心,如果测试数据比较刁钻的话就不可能
23、 ac,而这题是一道比较典型的树型动态规划的题目,这题不但要考虑子节点对他的根节点的影响,而且每放一个士兵,士兵所在位置既影响他的子节点也影响了他的根节点。不过状态还是很容易来表示的,动规实现也不是很难,不过这在这些例题中也有了些“创新”了。而且这题不是一个对二叉树的 dp,而是对一颗普通树的 dp,所以更具代表性。源程序代码: program bluewater; constmaxn=1500;var i,j,k,l:long;m,n,p,q:long;a:array0.maxn,0.maxn of;b:array0.maxn of longc:array0.maxn of;function leaf(x:longvar i,j:long;):;t:begin t:=true;for i:=0 to n-1 do if ax,i then beg leaf:=t;end;:=false;break;end;function treedp(x:long):long; var i,j,k,l:long;begin j:=0;addk:=0;leafl:=0;not put not leaf for i:=0 to n-1 doif (ax,i) and (xi) then if leaf(i) then inc(k) else beginj:=j+treedp(i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 建立安全检查责任制制度
- 总工安全管理责任制度
- 卫生机构监管责任制度
- 保密管理措施及责任制度
- 诊所首诊医师责任制度
- 消防安全领导责任制度
- 幼儿园保卫主体责任制度
- 公司治安工作责任制度
- 大排档安全生产责任制度
- 幼儿园帮扶责任制度汇编
- 2026年山东圣翰财贸职业学院单招职业技能考试题库及答案解析
- GB 14249-2026电子衡器安全要求
- 2026第二师铁门关市公安局招聘警务辅助人员(36人)笔试备考题库及答案解析
- 瘢痕课件教学课件
- 人教版七年级历史上册(部编版)课件【全册】
- 车工工艺学与技能训练
- 部编人教版八年级下册语文全册专题训练(含答案)
- 绳索取芯钻具使用说明书
- 江苏公路桥梁基本表格及用表说明
- 人教版五年级上册数学《观察物体》练习题
- 颅脑肿瘤垂体腺瘤
评论
0/150
提交评论