〖问题2〗乘船问题——信息学NOI联赛辅导专题.doc

〖问题2〗乘船问题——信息学NOI联赛辅导专题.doc

  1. 1、本文档共3页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
〖问题2〗乘船问题——信息学NOI联赛辅导专题.doc

〖〗 NOI竞赛辅导 王建德教练讲稿 有N个人需要乘船,而每船最多只能载两人,且必须同名或同姓。求最少需要多少条船。 两点间用实线表示同姓,虚线表示同名 【】m个结点的二叉树Tm,需要船的数量(Tm对应的连通分量的覆盖边数)为boat[m]=[m/2](m(N)。 证明: 当m=1,m=2,m=3时命题显然成立。 假设当mk(k3)时命题成立,那么当m=k时,我们首先从树中找到一个层次最深的结点k,并假设这个结点的父亲为p,即(p,k)为非桥边。那么,此时有且只有以下三种情况(结点中带有阴影的是p结点): 如图(a),p只有一个儿子。此时删去p和p唯一的儿子,Tk就成为了Tk-2,则boat[k]=boat[k-2]+1=[(k-2)/2]+1=[k/2]。 如图(b),p有两个儿子,并且p是其父亲的左儿子。此时可删去p和p的右儿子,并可将p的左儿子放到p的位置上。同样地,Tk成为了Tk-2,boat[k]=boat[k-2]+1=[k/2]。 如图(c),p有两个儿子,并且p是其父亲的右儿子。此时可删去p和p的左儿子,并可将p的右儿子放到p的位置上。情况与(2)十分相似,易得此时得boat[k]=boat[k-2]+1=[k/2]。 综合(1)、(2)、(3),当m=k时,boat[k]=[k/2]。 最后,综合(i)、(ii),对于一切m(N,boat[m]=[m/2]。 proc try(father:integer;var root:integer;var rest:byte);{输出root为树根的子树的乘船方案,father=0表示root是其父亲的左儿子;father=1表示root是其父亲的右儿子,rest表示输出子树的乘船方案后,是否还剩下一个根结点未乘船} visit[root]:=true; {标记root已访问} 找到一个与root同姓且未访问的结点j; if jn+1 then try(0,j,lrest); 找到一个与root同名且未访问的结点k; if kn+1 then try(1,k,rrest); if (lrest=1) xor (rrest=1) {判断root是否只有一个儿子,情况一} then if lrest=1 then输出lrest和root同乘一条船 else 输出rrest和root同乘一条船; rest:=0; else if (lrest=1) and (rrest=1) {判断root是否有两个儿子} then if father=0 then 输出rrest和root同乘一条船; root:=j; {情况二} else 输出lrest和root同乘一条船; root:=k; {情况三} rest:=1; else rest:=1; for j:=1 to n do if not visit[j] {若有一个人未访问,则证明其处在另一棵子树中} then i:=j; try(1,i,rest);{以这个未访问的点为根结点建立子树,并输出该子树中所有人的乘船方案} if rest=1 {最后是否还剩下一个人} then 输出i乘一条船; inc(total); 输出船的总数total;

文档评论(0)

wsh1288 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档