《GEMS》解题报告.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
《GEMS》解题报告

珠宝 给一棵n个结点的树,给每个点安排一个正整数编号,使得相邻点具有不同的编号,编号的总和尽量小。 输入   第一行:n(n=50,000) 以下n-1行,每行两个数u,v(1=u,v=n),表示u 和v有一条边 输出   仅一行,为最小编号和 样例输入 8 1 2 1 3 1 4 1 5 5 6 5 7 5 8 样例输出 11 分析: 看完题目,很自然地联想到树型DP,而且也不难得到状态表示方法。先根据输入的数据构造出一棵树,然后从树的叶子结点往上倒推。设F[I,J]表示以I为根的子树在I的编号为J时,可以得到的最小编号和。 状态转移方程为:F[I,J] = Min{∑F[I1, J1]} + J 其中I1表示I的一个子结点编号,J1为不同于J的一个自然数。 很显然,在最优方案中,所有解的编号都是不可能超过N的。因此不难推出算法的时间复杂度为O(N^3),空间复杂度为O(N^2)。这对于本题的规模来说,是无法承受的。 分析一下几个比较小的数据,会发现在最优方案中,最大的编号全部都没有达到N,不妨设其为M。而且凭感觉来看,M比N要小很多。很自然地,我们会考虑计算出这个比N小的M,然后DP的时候只要对每个点考虑编号为1到M的状态即可。这样时间复杂度就降为O(NM^2),空间复杂度降为O(NM)。但是M究竟怎么得到呢?我们发现这是很难计算的,而且也不太好估算出一个界(至少我没有想到好的方法)。事实上可以采取一种比较无奈的方法。因为N最大为50000,时限为1S,所以要想算法在理论上的最坏情况下不超时,M取30左右比较保险,实践证明,M取30足以通过所有测试数据了。 似乎通过上面的分析本题已经解决得差不多了,但M毕竟是“贪”出来的,正确性不能得到理论上的证明,我们不妨从算法优化的角度来考虑这个问题。还是回到最初的DP算法。仔细推敲一下就会发现,F[I,1 .. M]这M个状态中,能够在以后的状态转移中真正利用到的只有两个,它们是这M个状态中值最小的两个。因此,可以将算法做一下改进,设F[I,1],F[I,2],NUM[I,1],NUM[I,2]分别表示F[I,1..M]中值最小的两个,以及此时点I的编号。状态转移方程只要在原来的基础上做下改进即可: 先求出F[I,1 .. M],再保留其中最小的两个。为了描述方便,用辅助数组F1[1 .. M]表示F[I,1 .. M],那么有 F1[J] = ∑F[I1,J1] + J 其中I1表示I的子结点。若NUM[I1,1] = J,则J1 = 2,否则J1 = 1 此时时间复杂度降为O(N^2),空间复杂度降为O(N)。时间方面仍然不理想。再分析一下,可以发现,若找到一个最小的J满足J + ∑F[I1,1] = F[I,2],那么F[I,J..M]显然都是不小于F[I,2]的,所以此时可以停止计算后面的状态了。类似的,在求某一个F1[J]的过程中,如果当前累加变量的值不小于F[I,2],也可以停止计算F1[J]啦。 这两个剪枝加上去后,该算法可以瞬间通过所有数据。而且分析一下就会发现,该算法的时间复杂度大约为O(KN),K是一个相对于N来说比较小的系数。 参考程序: const maxn = 50000; type tg = array[1 .. maxn] of longint; var g : array[1 .. maxn] of ^tg; d, fa, son : array[1 .. maxn] of longint; f, num : array[1 .. maxn, 1 .. 2] of longint; n, m, s, min : longint; procedure init; var i, x, y : longint; begin readln(n); for i :=1 to n - 1 do begin readln(x, y); inc(d[x]); inc(d[y]); end; for i :=1 to n do begin getmem(g[i], sizeof(longint) * d[i]); d[i] :=0; end; readln(n); for i :=1 to n - 1 do begin readln(x, y); inc(d[x]); g[x].[d[x]] :=y; inc(d[y]); g[y].[d[y]]

文档评论(0)

xy88118 + 关注
实名认证
文档贡献者

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

1亿VIP精品文档

相关文档