发博文
正文 字体大小:

USACO:Crafting Winning Solutions

(2009-03-21 22:25:43)
标签:

usaco

winning

solutions

it

分类: 杂谈

赢得比赛解决方案

(这篇文章没有翻译我用google翻译了一下,并作了一点改动,后面基本没改,仅供参考)

A good way to get a competitive edge is to write down a game plan for what you're going to do in a contest round.一个好方法获得竞争优势是写下你将要竞赛的计划。 This will help you script out your actions, in terms of what to do both when things go right and when things go wrong.这将帮助您策划您的行动,在做什么事情时,都有可能让事情出差错。This way you can spend your thinking time in the round figuring out programming problems and not trying to figure out what the heck you should do next...这样你可以把时间花在你的思想的全面规划问题上,而不是试图找出你应该做的下一个问题... it's sort of like precomputing your reactions to most situations.这有点像你大多数情况下precomputing的反应。

Mental preparation is also important.心理上的准备也很重要。

一回合的Game Plan For A Contest Round竞赛计划

第一Read through ALL the problems FIRST; sketch notes with algorithm, complexity, the numbers, data structs, tricky details, ...通读所有问题;试着推想到的算法(写下来),复杂性,数字,数据structs ,微妙的细节, ...

  • Brainstorm many possible algorithms - then pick the stupidest that works!集思广益,在许多可能的算法中挑选最简单的!
  • DO THE MATH!做数学归纳、推理! (space & time complexity, and plug in actual expected and worst case numbers) (空间和时间复杂度,并推出实际预期和最坏的情况下的数字)
  • Try to break the algorithm - use special (degenerate?) test cases试着打破常规的算法-使用特殊方法(退化? )测试案例
  • Order the problems: shortest job first, in terms of your effort (shortest to longest: done it before, easy, unfamiliar, hard)整理问题:最短的工作首先做,在你努力的进程中(最短到最长的:这样做之前,简单,不熟悉,很难)

Coding a problem - For each, one at a time:编写一个程序-对于每一个,一次写一个:

  • Finalize algorithm最后的算法
  • Create test data for tricky cases创建苛刻的测试数据
  • Write data structures写入数据结构
  • Code the input routine and test it (write extra output routines to show data?)代码输入常规和测试(写出额外输出例程显示的数据? )
  • Code the output routine and test it代码的输出常规测试
  • Stepwise refinement: write comments outlining the program logic逐步求精:写评论概述程序逻辑
  • Fill in code and debug one section at a time填写代码和调试,一次一个区段
  • Get it working & verify correctness (use trivial test cases)获得工作及正确性验证(使用较小的测试案例)
  • Try to break the code - use special cases for code correctness试着打破目前的程序套路-使用特殊的正确的代码
  • Optimize progressively - only as much as needed, and keep all versions (use hard test cases to figure out actual runtime)逐步优化-只有多达需要,并保持所有版本(使用硬盘的测试情况下,计算出实际运行时)

Time management strategy and "damage control" scenarios时间管理的策略和“毁坏控制”的设想

计划计划各种(可预见的! )差错的状况;想象问题,您可能需要和找出您想如何作出反应。 The central question is: "When do you spend more time debugging a program, and when do you cut your losses and move on?".中心问题是: “何时你花更多的时间调试程序,何时你将你的损失排除并继续前进? ” 。 Consider these issues:考虑这些问题:

  • How long have you spent debugging it already?你花费多久调试?
  • What type of bug do you seem to have?你看上去像何种类型的错误?
  • Is your algorithm wrong?是你的算法错了吗?
  • Do you data structures need to be changed?你的数据结构需要改变?
  • Do you have any clue about what's going wrong?对于你的错误,你有什么线索吗?
  • A short amount (20 mins) of debugging is better than switching to anything else; but you might be able to solve another from scratch in 45 mins.较短的( 20分钟)的调试优于其它任何一种方式;但您可以从零开始编45分钟。
  • When do you go back to a problem you've abandoned previously?你什么时候回到问题在您放弃以前?
  • When do you spend more time optimizing a program, and when do you switch?当你花更多的时间优化的程序,你何时开关?
  • Consider from here out - forget prior effort, focus on the future: how can you get the most points in the next hour with what you have?从这里考虑出-忘记之前的努力,着眼于未来:你怎么能把握最大的重点在未来的时间里,通过你自己?

Have a checklist to use before turning in your solutions:有一个清单,然后使用你的解决方案:

比赛比赛的最后五分钟你还在编程?

  • Turn asserts off.马上结束。
  • Turn off debugging output.关闭调试输出。

Tips & Tricks提示和技巧

  • Brute force it when you can您可以暴力搜索
  • KISS: Simple is smart!KISS原则:简单就是智慧!
  • Hint: focus on limits (specified in problem statement)提示:重点在时限 (指明的问题)
  • Waste memory when it makes your life easier (if you can get away with it)浪费空间当它让您的生活更轻松(如果你能逃脱它)
  • Don't delete your extra debugging output, comment it out请勿删除您额外的调试输出,注释掉
  • Optimize progressively, and only as much as needed逐步优化,并且尽可能多。
  • Keep all working versions!保留所有工作版本!
  • Code to debug:代码调试:
    • whitespace is good,空白是好的,
    • use meaningful variable names,使用有意义的变量名,
    • don't reuse variables,不重复使用的变量,
    • stepwise refinement,逐步求精,
    • COMMENT BEFORE CODE.注释,然后再编号。
  • Avoid pointers if you can避免指针如果你可以的话(谁会没事干用这个(^-^))
  • Avoid dynamic memory like the plague: statically allocate everything.避免动态内存像瘟疫泛滥:静态分配一切。
  • Try not to use floating point; if you have to, put tolerances in everywhere (never test equality)尽量不要使用浮点;如果您要,把公差放在各处(从未测试平等)
  • Comments on comments:评论意见:
    • Not long prose, just brief notes不长的散文,只是简要说明
    • Explain high-level functionality: ++i; is worse than useless解释高层次的功能:  ++i; 不如不用
    • Explain code trickery解释代码权谋
    • Delimit & document functional sections划定及文件功能部分
    • As if to someone intelligent who knows the problem, but not the code如某人有智慧知道这个问题,但没有代码
    • Anything you had to think about你有什么额外的想法
    • Anything you looked at even once saying, "now what does that do again?"任何你看着甚至一度表示, “现在是什么做的? ”
    • Always comment order of array indices总是评论顺序排列指数
  • Keep a log of your performance in each contest: successes, mistakes, and what you could have done better; use this to rewrite and improve your game plan!保持的记录你的表现在每一个比赛:成功,错误,你可以做得更好;使用此重写和改善你的计划!

Complexity复合问题

Basics and order notation基础和秩序的符号

The fundamental basis of complexity analysis revolves around the notion of ``big oh'' notation, for instance: O( N ).根本基础的复杂性分析,围绕着这一概念的``大啊''符号,例如:为O n ) 。 This means that the algorithm's execution speed or memory usage will double when the problem size doubles.这意味着,该算法的执行速度和内存使用量将增加一倍的问题时。 An algorithm of O( N 2 ) will run about four times slower (or use 4x more space) when the problem size doubles.算法为O n 2 )将运行速度的4倍(或使用4倍的空间)的问题时。 Constant-time or space algorithms are denoted O(1).恒时间或空间的算法是指为O ( 1 ) 。 This concept applies to time and space both; here we will concentrate discussion on time.这一概念适用于时间和空间两个;在这里,我们将集中讨论的时间。

One deduces the O() run time of a program by examining its loops.一个推导出的O ( )运行时的程序审查其循环。 The most nested (and hence slowest) loop dominates the run time and is the only one mentioned when discussing O() notation. A program with a single loop and a nested loop (presumably loops that execute N times each) is O( N 2 ), even though there is also a O( N ) loop present.最嵌套(因而慢)闭环控制运行时间,并且是唯一一个提到在讨论()符号。程序的单回路和一个嵌套循环(大概循环每执行N次)为O N 2 ) ,即使有也是一个为O n )环本。

Of course, recursion also counts as a loop and recursive programs can have orders like O( b N ), O( N! ), or even O( N N ).当然,也算作递归循环和递归程序可以有订单像O(b N), O(N!),或者甚至为O n n )段。

Rules of thumb经验法则

  • When analyzing an algorithm to figure out how long it might run for a given dataset, the first rule of thumb is: modern (2004) computers can deal with 100M actions per second.在分析一个算法,计算出多久,它可能会为给定的数据集,第一个法则是:现代( 2004 )计算机可以处理每秒百兆行动。 In a five second time limit program, about 500M actions can be handled.在五秒时间限制的计划,大约500M可处理。 Really well optimized programs might be able to double or even quadruple that number.很好的优化程序可以翻一番甚至翻两番,这个数字。 Challenging algorithms might only be able to handle half that much.具有挑战性的算法可能只能够处理的一半多。 Current contests usually have a time limit of 1 second for large datasets.目前竞赛通常有时间限制为1秒钟的大型数据集。
  • 16MB maximum memory use最高的16MB内存使用
  • 2 10 ~approx~ 10 3210 ~约为~ 10 3
  • If you have k nested loops running about N iterations each, the program has O( N k ) complexity.如果您有k嵌套循环运行约ñ反复每个,该计划已经为O(N k)的复杂性。
  • If your program is recursive with b recursive calls per level and has l levels, the program O( b l ) complexity.如果您的计划是递归递归调用 B每一级,并的水平,该计划O(b l)的复杂性。
  • Bear in mind that there are N! permutations and 2 n subsets or combinations of N elements when dealing with those kinds of algorithms.记住,有N!置换和2 n不适用或组合N在处理这些种算法。
  • The best times for sorting N elements are O( N log N ).最佳时间排序N元素为O(N log N)段。
  • DO THE MATH! Plug in the numbers. DO THE MATH!插入的数量。

Examples实例

A single loop with N iterations is O( N ):单循环 N反复为O n ) :
  sum 0
  for to n
    sum sum i

A double nested loop is often O( N 2 ):双重嵌套循环往往是为O n 2 ):

fill array with elements # fill array with elements
for to n-1
  for to n
    if (a[i] a[j])
         swap (a[i], a[j])
Note that even though this loop executes N x (N+1) / 2 iterations of the if statement, it is O( N 2 ) since doubling N quadruples the execution times.请注意,虽然这个循环执行N x (N+1) / 2迭代的if语句,它为O N 2 )自一倍ñ四倍的执行时间。

Consider this well balanced binary tree with four levels:审议这个很好的平衡二叉树的四个层次:

An algorithm that traverses a general binary tree will have complexity O( 2 N ).一个算法,遍历一般二叉树将复杂性为O(2 N)段。

Solution Paradigms解决范式

Generating vs. Filtering生成 vs 过滤

Programs that generate lots of possible answers and then choose the ones that are correct (imagine an 8-queen solver) are filters .项目所产生的大量可能的答案,然后选择那些是正确的(想象一个8皇后解)的过滤器 。 Those that hone in exactly on the correct answer without any false starts are generators .那些磨练完全正确的答案没有任何错误的开始是发电机 。 Generally, filters are easier (faster) to code and run slower.一般说来,过滤器更容易(快)的代码和运行速度较慢。 Do the math to see if a filter is good enough or if you need to try and create a generator.做数学,看看是否过滤器是不够好,或者如果您需要尝试,创造一个发电机。

Precomputation

Sometimes it is helpful to generate tables or other data structures that enable the fastest possible lookup of a result. This is called precomputation (in which one trades space for time).有时是有益的生成表格或其他数据结构,使尽可能快地查找的结果。这就是所谓的 (在哪一个行业的空间,时间)。 One might either compile precomputed data into a program, calculate it when the program starts, or just remember results as you compute them.人们也许可以算数据汇编成一个程序,计算出它的程序启动时,或只记得你的计算结果作为他们。 A program that must translate letters from upper to lower case when they are in upper case can do a very fast table lookup that requires no conditionals, for example.程序必须把信上以较低的情况下,他们是大写可以做一个非常快速查表无需条件,例如。 Contest problems often use prime numbers - many times it is practical to generate a long list of primes for use elsewhere in a program.比赛的问题经常使用素数-这是多少次的实际构造了一长串素用于其他地方的一个程序。

Decomposition (The Hardest Thing At Programming Contests)分解(最难在编程竞赛)

While there are fewer than 20 basic algorithms used in contest problems, the challenge of combination problems that require a combination of two algorithms for solution is daunting.虽然有不少于20个基本算法竞赛中使用的问题,面临的挑战相结合的问题,需要结合两种算法的解决方案是艰巨的。 Try to separate the cues from different parts of the problem so that you can combine one algorithm with a loop or with another algorithm to solve different parts of the problem independently.试图分开线索来自不同地方的问题,以使您可以将一个算法循环或与其他算法来解决不同地区的独立问题。 Note that sometimes you can use the same algorithm twice on different (independent!) parts of your data to significantly improve your running time.请注意,有时候你可以使用相同的算法在不同的两倍(独立! )的部分数据,大大提高您的运行时间。

Symmetries对称性

Many problems have symmetries (eg, distance between a pair of points is often the same either way you traverse the points). Symmetries can be 2-way, 4-way, 8-way, and more.很多问题对称性(如之间的距离一分往往是相同的方式,您可以穿越点) 。对称性可2路, 4路, 8路,等等。 Try to exploit symmetries to reduce execution time.试图利用对称性,以减少执行时间。

For instance, with 4-way symmetry, you solve only one fourth of the problem and then write down the four solutions that share symmetry with the single answer (look out for self-symmetric solutions which should only be output once or twice, of course).例如,与4路对称,你只有四分之一解决的问题,然后写下了四个解决方案,份额对称性与单一的答案(寻找自我对称解决方案,这些方案应只输出一次或两次,当然)。

Forward vs. Backward转寄vs落后

Surprisingly, many contest problems work far better when solved backwards than when using a frontal attack.令人惊讶的是,许多竞赛工作好得多问题解决倒退时比使用时迎头。 Be on the lookout for processing data in reverse order or building an attack that looks at the data in some order or fashion other than the obvious.密切注意处理数据顺序相反或建立了攻击,期待中的数据,在一些命令或方式以外的其他显而易见的。

Simplification简化

Some problems can be rephrased into a somewhat different problem such that if you solve the new problem, you either already have or can easily find the solution to the original one; of course, you should solve the easier of the two only.有些问题是可以改写成一个略有不同的问题,例如,如果你解决新问题,您可能已经或可以很容易地找到解决原来的那个,当然,你应该比较容易解决的两个只。 Alternatively, like induction, for some problems one can make a small change to the solution of a slightly smaller problem to find the full answer.另外,像上岗,对一些问题可以作一个小的变化,为解决一个略小问题找到充分的答案。

 

阅读 评论 收藏 转载 打印举报
已投稿到:
  • 评论加载中,请稍候...

       

    验证码: 请点击后输入验证码 收听验证码

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 不良信息反馈 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有