ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:73.65KB ,
资源ID:10543481      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10543481.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(衡阳市八中day2修正版solution.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

衡阳市八中day2修正版solution.docx

1、衡阳市八中day2修正版solution第一题记得Mario 64上有一个游戏,古代背景,点击一个格子就会使得它周围3x3范围内的格子翻动,要求在3步之内把格子翻成上面的图案。此题类似,只不过是翻动本身和上下左右范围内的5个格,为怎样翻动才能翻成全为0的状态。要求输出翻动方式(1是翻动,0是不翻动)且按字典序排列最靠前的那个。首先注意字典序:记住,越靠上及越靠右的格子字典顺序越靠前。故第一个1越靠下,靠左最好。本题的搜索不太容易想到。如果直接暴搜,O(2(n2)的时间复杂度会算到地老天荒所以观察,可以发现,如果第一行的翻动方式确定了,就可以唯一确定第二行的翻动方式。原因是翻动过的第一行内,如果

2、是1的格子,下面第二行必须翻动,第一行如果为0,下面第二行必须不翻动。否则第一行的非0值就再也没有什么东西可以救它了。于是时间复杂度直降O(2n),可以搜索了。无需剪枝,125MS可以接受。第二题:The starting point here is a dynamic programming algorithm. Arbitrarily root the tree and consider cutting off a particular subtree in a soldering. This leaves one (or none if a wire was cut off at its

3、 endpoints) cut wire which extends out of the subtree to the parent and a set of wires that are wholly within the subtree. Now, note that all that is relevant is the length of the cut wire within the subtree and the total cost of all the other wires. This is because the cut wire is the only wire who

4、se cost depends on the rest of the soldering.This gives a relatively simple dynamic programming solution: for each vertex (defining a subtree) store, for each possible cut wire length, the minimum cost of the other wires; if there is no cut wire this can be taken as a wire of length 0. We will compu

5、te these from the bottom up. To compute these values, note that if there is a cut wire it must extend down to one of the children; the cost for a cut wire going through a particular child is the cost for the cut wire through the childs subtree plus the minimum cost soldering covering each of the oth

6、er subtrees. If there is no cut wire, then the edge going to the parent must be soldered onto the middle of another wire; then one can just check all pairs of lengths and distinct children to find two cut wires for two children to merge into into one wire. Now, note that the maximum length cut wire

7、for each subtree is the number of nodes it contains, so the number of pairs of lengths for any two distinct children is at most the number of pairs of nodes in the two children; summing over all children this is the number of nodes whose lowest common ancestor is the root of the subtree. Then the to

8、tal work done over the whole algorithm is only the total number of pairs of nodes, or O(N2).Now, at this point it will be convenient to assume, in the discussion of the algorithm, that each vertex has at most two children. In fact, this is not a problem: a vertex V with more children can be split up

9、 by giving it a direct edge to one of its children and attaching the remainder to a new vertex V with an edge to it from V of length 0 (the length does not break the algorithm although all edges in the problem were of length 1), then iterating this until no vertex has more than two children.To furth

10、er reduce the runtime, one must note the convexity properties of the squaring of the length. If one looks at a length/cost pair (l, c) for a subtree, it corresponds to the function (L+l)2+c where L is the length of the cut wire outside the subtree. But one only cares about those functions that are t

11、he minimum for some value of L: since (L+l)2+ c = L2+ 2L * l + (l2+ c), this is the lower envelope of these functions, equivalent to a convex hull. All pairs not in the envelope can be deleted. One can then binary search the convex hull to find the optimal pairing with any particular length of the w

12、ire outside the subtree. Then to find the optimal pair of lengths in the two children to merge into one wire, one can simply take all the lengths in the smaller subtree and binary search the convex hull in the larger subtree to find the best thing within that subtree to pair it with. Finally, to eff

13、iciently find the convex hulls for all subtrees, one can represent the convex hulls with binary search trees (std:set does fine here) and to get the possibilities from either child, one can offset the values in the larger child subtrees convex hull (by storing offset values that are added to all the

14、 pairs in the hull, since both length and cost change as you merge subtrees) and then insert each pair (offset) from the smaller subtree into it. The total number of operations on the binary search trees is then at most the sum of the sizes of the smaller child subtree from each node (in fact it can

15、 be smaller as the convex hull can have fewer elements than the size of the subtree). This can be shown to be O(N log N): one can consider the number of times each position gets merged into a larger group, and note that it is always less than log N since with each merge only the values in the smalle

16、r half are incremented. Each tree operation is O(log N), so the overall runtime is O(N log2N).Below is Neal Wus N2implementation:#include #include #include using namespace std;FILE *in = fopen (solder.in, r), *out = fopen (solder.out, w);const int MAXN = 50005;const long long LLINF = 1LL 60;int N, d

17、own MAXN;long long *dp MAXN, mindp MAXN;vector adj MAXN;void init_dfs (int num, int par) down num = 1; int par_ind = -1; for (int i = 0; i (int) adj num.size (); i+) int child = adj numi; if (child = par) par_ind = i; continue; init_dfs (child, num); down num = max (down num, down child + 1); if (pa

18、r_ind != -1) adj num.erase (adj num.begin () + par_ind);void solve_dfs (int num) for (int i = 0; i 1) for (int i = 0; i (int) adj num.size (); i+) dp1 += mindp adj numi; long long best_two = LLINF; for (int i = 0; i (int) adj num.size (); i+) for (int j = i + 1; j (int) adj num.size (); j+) int chil

19、d1 = adj numi, child2 = adj numj; for (int a = 1; a = down child1; a+) for (int b = 1; b = down child2; b+) best_two = min (best_two, dp child1a + dpchild2b + 2LL * a * b - mindp child1 - mindp child2); dp1 += best_two; dp num = new long long down num + 1; dp num1 = dp1; if (adj num.size () = 1) dp

20、num1 = LLINF; dp num0 = mindp adj num0; else dp num0 = dp num1 - 1; for (int k = 1; k down num; k+) long long sum = 0, best_link = LLINF; for (int i = 0; i (int) adj num.size (); i+) int child = adj numi; sum += mindp child; if (k = down child) best_link = min (best_link, dp childk - mindp child); d

21、p numk + 1 = sum + best_link + 2 * k + 1; mindp num = LLINF; for (int k = 1; k = down num; k+) mindp num = min (mindp num, dp numk); for (int i = 0; i (int) adj num.size (); i+) delete dp adj numi;int main () fscanf (in, %d, &N); for (int i = 1, a, b; i N; i+) fscanf (in, %d %d, &a, &b); a-; b-; adj

22、 a.push_back (b); adj b.push_back (a); init_dfs (0, -1); solve_dfs (0); fprintf (out, %lldn, dp 00); return 0;And below is Michael Cohens impressive full implementation:#include #include #include #define endl nusing namespace std;struct poss long long depth; long long cost; long long takeover; bool

23、tcheck;bool operator(poss a, poss b) if (a.tcheck | b.tcheck) return (a.takeover b.depth) return true; if (a.depth b.depth) return false; return (a.cost b.cost);int N;vector edges50000;bool visited50000;long long depth50000;long long offset50000;set* best50000;void recurse(int node) visitednode = tr

24、ue; long long bestPair = -1; long long allSoFar = 0; for (int i = 0; i edgesnode.size(); i+) if (visitededgesnodei) continue; depthedgesnodei = depthnode+1; recurse(edgesnodei); long long tadd; poss when = 0, 0, -depthnode, true ; set:iterator which = bestedgesnodei-upper_bound(when); which-; tadd =

25、(depthnode-which-depth)*(depthnode-which-depth)+which-cost+offsetedgesnodei; if (bestPair != -1) bestPair += tadd; if (bestnode = NULL) bestnode = bestedgesnodei; offsetnode = offsetedgesnodei; else set* s = bestnode, * t = bestedgesnodei; long long os = offsetnode+tadd, ot = offsetedgesnodei+allSoF

26、ar; if (s-size() size() set* tem = s; s = t; t = tem; int to = os; os = ot; ot = to; for (set:iterator it = t-begin(); it != t-end(); it+) poss when = 0, 0, it-depth-2*depthnode, true ; set:iterator which = s-upper_bound(when); which-; long long thisPair =(it-depth+which-depth-2*depthnode)*(it-depth

27、+which-depth-2*depthnode)+it-cost+which-cost+offsetnode+offsetedgesnodei; if (bestPair = -1 | thisPair bestPair) bestPair = thisPair; for (set:iterator it = t-begin(); it != t-end(); it+) poss p = *it; p.cost += ot-os; set:iterator where = s-insert(p).first; bool killed = false; while (where != s-be

28、gin() set:iterator prev = where; prev-; if (prev-depth = where-depth) s-erase(where); killed = true; break; p.takeover =(where-cost-prev-cost+where-depth*where-depth-prev-depth*prev-depth)/(2*prev-depth-2*where-depth); while (2*prev-depth-2*where-depth)*p.takeover cost-prev-cost+where-depth*where-depth-prev-depth*prev-depth)p.takeover+; s-erase(where); where = s-insert(p).first; if (where-takeover takeover) s-erase(prev); else break; if (killed) continue; if (where = s-begin() p.takeover = -1000000000; s-erase(where); where = s-insert(p).first; set:iter

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1