NOIP编程比赛

NOIP编程比赛

NOIP教学参考

信息学竞赛 培训资料

NOIP题解

信息学奥林匹克竞赛 wiki

全国青少年信息学奥林匹克竞赛 官网

赛题

NOIP:全国青少年信息学奥林匹克联赛(National Olympiad in Informatics in Provinces简称NOIP)自1995年至今。
      每年由中国计算机学会统一组织。 NOIP在 同一时间、不同地点以各省市为单位由特派员组织。
      全国统一大纲、统一试卷。初、高中或其他中等专业学校的学生可报名参加联赛。
      联赛分初赛和复赛两个阶段。初赛考察通用和实用的计算机科学知识,以笔试为主。
      复赛为程序设计,须在计算机上调试完成。参加初赛者须达到一定分数线后才有资格参加复赛。
      联赛分普及组和提高组两个组别,难度不同,分别面向初中和高中阶段的学生。
      获得提高组复赛一等奖的选手即可免试由大学直接录取。

冬令营:全国青少年信息学奥林匹克冬令营(简称冬令营)自1995年起。每年在寒假期间开展为期一周的培训活动。
      冬令营共8天,包括授课、 讲座、讨论、测试等。参加冬令营的营员分正式营员和非正式营员。
      获得NOI前20名的选手和指导教师为正式营员,非正式营员限量自愿报名参加。
      在冬令营授课的是著名大学的资深教授及已获得国际金牌学生的指导教师。

APIO: 亚洲与太平洋地区信息学奥赛(Asia Pacific Informatics Olympiad)简称(APIO)2007年创建,
      该竞赛为区域性的网上准同步赛,是亚洲和太平洋地区每年一次的国际性赛事,
      旨在给青少年提供更多的赛事机会,推动亚太地区的信息学奥林匹克的发展。
      APIO每年5月举行,由不同的国家轮流主办。每个参赛团参赛选手上限为100名,
      其中成绩排在前6名的选 手作为代表该参赛团的正式选手统计成绩。
      APIO中国赛区由中国计算机学会组织参赛,获奖比例将参照IOI。

选拔赛:选拔参加国际信息学奥林匹克中国代表队的竞赛(简称选拔赛)。
      IOI的选手是从获NOI前20名选手中选拔出来的,获得前4名的优胜者代表中国参 加国际竞赛。
      选拔科目包括:NOI成绩、冬令营成绩、论文和答辩、平时作业、选拔赛成绩、口试。
      上述项目加权产生最后成绩。

IOI: 出国参加国际信息学奥林匹克竞赛(International Olympiad in Informatics)简称(IOI)。
      由中国计算机学会组织代表队,代表中国参加国际每年一次的IOI。中国是IOI创始国之一。
      IOI2000由中国主办,CCF承办。出国参赛得到中国科协和国家自然科学基金委的资助。
      自1989年开始,我国在NOI(网上同步赛99年开始)、NOIP、冬令营、选拔赛的基础上,
      组织参加国际信息学奥林匹克(IOI)竞赛。十几年中选拔75人次参加了 IOI,
      累计获金牌46块、银牌17块,铜牌12块。这些选手不仅在国际大赛中有好的表现,
      而且在现代的信息学科上也大展才华。

2018年3月份,教育部通知全面取消中学生学科奥林匹克竞赛等全国性高考加分项目,那么竞赛没有用了吗?

答案是否定的。虽然高考加分取消了,但是降分录取却更多了。

那自主招生降分录取是什么呢?

对于大学来说,要看考生的特长是否与大学的要求一致。如果一致,想收下这名有特长的学生,大学就会采取降分录取,但仅限于录取到和学生特长吻合的专业;如果不一致,即便考生的特长特别牛,不是大学所需要的,也不能通过自主招生降分。

对考生来说,要自己去挨个申请参加自主招生计划的大学,大学会组织专业老师来评定,看学生的这项特长到底符合不符合大学的招生要求。如果确实符合大学专业需要的人才标准,那么大学就会降分欢迎进来!

高考加分对大多数学生是不公平的,不能因为考生具有某些特长,就可以在高考时得到优厚待遇,这与考试公平相背离。自主招生降分录取,对于竞赛特长生来说,给他一个发挥特长的平台,通过继续深造,成为国家一些领域的顶尖人才,否则就会埋没了人才。

高考题目越来越简单,如果单纯以高考分数作为选拔标准,大学可能没有招收到适合培养的人才。因此,现在大学纷纷更加看重自主招生项目。

自招的初衷是为了招收对某学科有突出特长和兴趣的孩子,但实际上五大学科竞赛(数理化生和信息学)逐渐成了唯一的自招标准。

最新统计,在清北2017级新生中,共有864名完全通过竞赛保送或签约,并最终录取清北的学生,其中国家集训队直接保送清华的257名,全国决赛金牌降一本线签约清本的142名,省一等奖及以上通过暑期竞赛营、金秋营、生科营、工科挑战营取得签约或加分的465名。另外,一部分有竞赛学习经历的学生,凭借年级排名通过学科营、综合评价等其他途径获得了降分。

当然,清北对于竞赛的要求是非常高的,其竞赛招生体系是围绕着国家集训队-金牌展开,再对省一等奖、省队获得者进行多轮考核筛选。而其他大学要求就没那么高了。浙江大学、上海交通大学、中国科学技术大学,三所高校在招生简章当中明确要求,报名条件为“五大学科竞赛省一等奖”。很多985或者211大学的要求,其实只到省二,甚至双省三。

总之,如果一个学生仅仅有省一等奖,未能通过清北金秋营等考试提前取得签约或降分,能够考虑的就是上海交通大学、浙江大学、复旦大学、中国科学技术大学的自主招生。如果一个学生仅仅有省二等奖、甚至省三等奖,实际上对其余学校的自主招生来说,已经很是够用了。

所以说,想要参加自主招生,竞赛成绩是门槛,是获得自主招生入场券的基本条件。自主招生考试是学校自己命题,考察学生的水平,考试内容也和竞赛内容有很大的相关性。所以作为自主招生敲门砖的奥赛获奖成绩,含金量一点都没有比以前低。

算法竞赛

指的是以算法(和数据结构)为核心主题的编程竞赛。算法竞赛一般要求在规定时间内做若干道题目,并以编程的方式解决问题,可以使用 C/C++/Pascal/Java 等语言(视比赛要求而定)。竞赛规则

算法竞赛胜利的目标不尽相同,但是,如果你能在规定时间内正确解答所有题目,那么你肯定是赢家。

线下竞赛

NOI 系列(中学生)

NOI 系列比赛是初中生和高中生参加的比赛。高中五大学科竞赛分别是数学、物理、化学、生物、信息学,其中信息学就是这个系列的比赛。

最底的比赛是分区联赛(NOIP)。NOIP 分普及组和提高组,普及组是初中生参加的,提高组是高中生参加的。NOIP 分初赛(笔试)和复赛(上机)。初赛晋级之后进入复赛。

关心竞赛的,初赛一般都能过。所以不需要担心什么了。

复赛的一些比赛情况(这里是 2014 年的情况):

  • 个人赛
  • 时间和题量:一般是 11 月的第三个周末。NOIP 复赛分两天进行,每天三道题。每道题 100 分,故总分 600 分。
  • 编程语言:使用 C/C++/Pascal 语言。因为是算法竞赛,所以不需要学习类和类库的用法。
  • 编程要求:每道题会有题目要求、输入输出格式和范例。你需要根据题目要求编程,严格按要求从文件中读取数据,进行处理,并严格按照要求输出答案。你需要按照要求将程序代码保存到电脑的指定路径。
  • 反馈:比赛结束之前不会有任何反馈。
  • 测评:比赛全部结束之后,程序会交到指定单位进行统一测评。每道题一般有 10 个固定的数据点,每个数据 10 分(有的题目是 20 个数据,每个数据 5 分)。测评系统会让你的程序读入这些数据,并检查你程序输出的结果是否与答案一致。
  • 测评结果:对于每个数据,存在以下几种状态。只有数据通过才能得分,错了不会额外扣分。假如一道题 10 个数据点你的程序通过了 6 个,那么这道题得 60 分。
    • 通过:你的程序输出的结果与答案一致,该数据点得分。
    • 编译错误:程序无法通过编译。由于有些省份不采用标准环境,所以很有可能在头文件上出问题。
    • 答案错误:答案错误,或者你的程序没有严格按照要求来输入输出数据。
    • 超时:你的程序没有在规定时间之内结束。不能得分。
    • 运行时错误:你的程序崩溃,同样不能得分。
  • 成绩:你最后知道的是通过的数据点累计的总分。分数越高越好。获得国家级一等奖之后有机会晋级,参加省队,从而继续参加更高级的比赛。最高级别是世界奥林匹克。
    • 因为现在参加奥赛不加分不保送,所以参加人数减少。只要你不生在变态的省份,拿一等奖其实不难。
  • 其他:
    • 不能携带参考资料。
    • 因为是黑盒测试,所以骗分合法。例如某题不会做,但是题目中有一句“如果无解,请输出-1”,那么你直接让程序输出 -1 也有可能得分。

ACM/ICPC 系列(大学生)

ACM/ICPC 本是美国的编程比赛。现在全世界都流行了(没错,朝鲜人也参加)。

ACM 比赛是大学生参加的比赛。与 NOIP 相比,ACM 的线下比赛比较多(学校举办的、省里举办的、某个学校的邀请赛……)。

ACM 比赛的情况:

  • 团体赛:三人共用一台电脑。
  • 时间和题量:5 个小时,10 道题左右。题量很大。
  • 编程语言:使用 C/C++/Java 语言。因为是算法竞赛,所以不需要学习类和类库的用法。
  • 编程要求:一般情况下题目是全英文的。每道题会有题目要求、输入输出格式和范例。你需要根据题目要求编程,严格按要求读取数据,进行处理,并严格按照要求输出答案。完成编程之后,可以立即提交代码并获得反馈信息。
  • 反馈:在提交代码之后立刻得到反馈。比赛期间可随时查看其他队伍的完成情况。最后一小时封榜(状态不再更新)。
  • 测评:提交代码之后立刻测评。一般情况下,测评系统会让你的程序读入一些标准数据,并检查你程序输出的结果是否与答案一致。
  • 测评结果:一般情况下,每道题会有以下几种状态。只有完全通过(Accepted)的题目才算完成。
    • 通过(Accepted):你的程序通过了所有的数据点,和答案全部一致。(和 NOIP 不同)
    • 编译错误(Compile Error)
    • 答案错误(Wrong Answer):答案错误,或者你的程序没有严格按照要求来输入输出数据。
    • 超时(Time Limit Exceeded):你的程序没有在规定时间之内结束。不能得分。
    • 运行时错误(Runtime Error):你的程序崩溃,同样不能得分。
  • 成绩:完成的题目越多,排名越靠前。完成题目同样多的话,总用时越少的排名越靠前。
    • 总用时是所有已完成题目的用时之和。每个题目的用时为实际用时加罚时。有一次不通过的提交,罚时就加 20 分钟。假如 A 题前三次提交不通过,第四次提交才通过,此时距离比赛开始已经 40 分钟,那么此题用时是 40+20x3=100 分钟。
    • 未通过的题目不计入总用时。
  • 其他:
    • 可以携带不限数量的纸质资料,不能带电子资料。因此许多参赛队伍会提前把一些常用的算法和数据结构的代码打印出来以节省编程时间。
    • 三个人只有一台电脑,团队之间要配合好。此外,在正式比赛中可通过打印服务打印代码。
    • 校外比赛一般都是校队的才有机会参加。

线上竞赛

Online Judge

很多在线测评网站不仅是题库,而且会不定期地办一些在线比赛。

比赛不一定有奖励,但是按照正式比赛的时间、正式比赛的要求去参加这些在线比赛会对提高比赛水平有很大帮助。

Codeforces

Codeforces(行内简称 CF)是俄罗斯一个著名的 Online Judge 网站,之所以将其单列出来,是因为它有一套独特的比赛规则。

  • 时间和题量:Codeforces 的比赛为 2 小时 5 道题。
    • 由于 Codeforces 采用的时区和中国不同,因此中国人常常需要熬夜(半夜 11 点或 12 点)参加比赛。
  • 分组:一般情况下,每场 Codeforces 比赛有两组(Div 1 和 Div 2),分别供积分(Rating)超过 1700 和不足 1700 的选手参加。新用户的积分是 1500。
    • 如果确实分为了 Div 1 和 Div 2,那么 Div 1 的 ABC 三题和 Div 2 的 CDE 三题是一样的。
    • Room:选择 Div 之后你会被随机分到一个房间(Room)中,一个房间大约 30 人。
  • 编程:同样是按照要求输入输出。可以使用各种主流编程语言 ,如 Python。
  • 测评:比赛期间系统只用前几组标准数据进行测评(实际上数据有几十甚至上百个)。如果这一小部分通过,那么被称作“Pretest Passed”。比赛结束后会使用全部数据进行统一测评,这被称作“System Test”。
  • 计分:如果某题通过,那么得分为当前分数减去 50 x 不成功的提交次数。某道题的分数是由比赛开始时的分数随时间线性减少得到的。最终得分以 System Test 为准。
  • Hack:这是 Codeforces 的特色之一。当某道题 Pretest Passed 之后,你可以选择锁定代码。锁定之后即可查看同房间内其他人的代码,并从中寻找漏洞,构造使其出错的数据。如果你的数据使对手的程序出错,那么就被称作“Successful hacking attempt”,你得 100 分。但是 Hack 失败,你会被扣 50 分。
    • 不管你是否锁定代码,只要其他人锁定了自己的代码,就可以 Hack 你。
    • Hack 成功的数据会被加入到标准数据中。

由于 Codeforces 的比赛模式很新颖,因此已经被 HDU 和 ACdream 等网站学习。题目质量也不错。

商业公司比赛

很多商业公司也会举办有奖竞赛,例如 TopCoder、百度程序之星等。

ACM 社团

想参加 ACM 比赛,当然要参加自己学校的 ACM 社团了,要不然哪里有去校外比赛的资格?

只要坚持到退役,你一定不会感到后悔。

辅导书

经典教材非《算法竞赛入门经典》(刘汝佳,清华大学出版社)莫属。最新版是第二版,封面以紫色为主色调。可从当当网上在线购买。

《算法艺术与信息学竞赛》也是刘汝佳的经典教材,不过难度很大,是给高手看的。

此外还有很多专为算法竞赛编写的竞赛书籍、算法与数据结构书籍,不妨多读一读。

在线测评网站

在线测评网站就是在网上做题、提交程序,然后查看反馈情况。有的够意思的网站会把详细情况告诉你,有的则不会。

很多题目可以到网上搜到题解,在想不出如何解决的情况下可以看一眼。

以下都是经典的在线测评网站。欢迎多刷题:

  • POJ:北京大学 OJ。
  • UVa:《算法竞赛入门经典》、《算法竞赛入门经典-训练指南》的练习题都在这里。网站辅助工具有 uHuntuvatoolkit
  • HDU (杭电ACM):杭州电子科技大学 OJ。刷题时请从第 11 页开始刷。
  • ZOJ:浙江大学 OJ。
  • Codeforces (CF):俄罗斯的网站。可以用 Python 等语言编程。Codeforces 的比赛也很有特色。
  • ACdream:这是一个社区组织的群和 OJ。
  • Virtual Judge:Virtual Judge 不是真正的在线测评,因为它的题目是通过机器人抓过来的,而且提交都是通过机器人到对应的网站去交。网站本身没有数据。Virtual Judge 还有一大特色就是“模拟参加”,也就是原比赛早已结束,但是整个过程看起来就像是你和其他用户“同时”竞技。由于 Virtual Judge 比赛质量差别很大,所以要谨慎对待。
  • USACO Training:美国官方训练教材。循序渐进(必须按顺序做题),并给详细数据和解析。

NOIP普及组初赛题型分析

初赛的考察内容的一部分是计算机的基础知识,比如进制转换,工作原理,算法原理、历史事件名人等。
这些对于大部分第一次参加noip的同学来说应该比较陌生,
这样的知识只能通过平时的积累,用心做几套历年真题,有意识的去记忆。
另一部分是数学内容,包括排列、组合等大概高中的数学知识,
当然小学和初中奥数基础比较扎实的同学应该也学过。
最后一部分是程序完成题目。如果说前面2部分还有补习的希望,
最后这一部分完全是靠你的做题基础,没有捷径,只能靠你平时多做题。

具体题型如下:
1.选择题:
  共20题,每题1.5分,共30分。考查的是基础知识和概念,一般说来,
  选择题只要多用心积累就可以了,很多选项都存在明显的错误,如果不确定答案,可以多采用排除法。
2.问题求解题:
  共2题,每题5分,共10分。近几年基本上有一个题目是组合题,在讲递推算法时,不少题目就是组合问题。
  试题会给出一个叙述较为简单的问题,要求学生对问题进行分析,找到一个合适的算法,并推算出问题的解。
  这类题目题目的模式比较固定,大家应当做做以前的题目。
3.程序阅读理解题:
  共4题,每题8分,共32分。题目给出一段程序(没有关于程序功能的说明),
  有时也会给出程序的输入,要求考生通过阅读理解该段程序给出程序的输出。
  这类题目也需要多做题目,并且培养良好的程序阅读和分析能力,
  人工方式模拟程序的每一步执行过程,程序不会很难,一定要细心,不要嫌麻烦。
4.程序完善题:共2题,每题14分,两题共28分。
  题目给出一段关于程序功能的文字说明,然后给出一段程序代码,在代码中略去了若干个语句并在这些位置给出空格,
  要求考生根据程序的功能说明和代码的上下文,填出被略去的语句。
  这类题目都会涉及到一些简单的算法(例如排序、查找、搜索、贪心、分治等) ,
  以及一些基本的数学知识和技巧,有些算法对一些同学来讲会比较陌生,不过也不要紧张,
  认真读代码,每个题目都有几个空要填写的,其中有些填空是比较明显可以做出来的,比如赋初值,循环条件之类的。
总之初赛对小学生和中学生来讲还是有一定难度的,但是只要平时做好准备,考场上细心答题,通过的概率还是很大的。

青少年计算机程序评级标准

算法设计是计算机科学的核心,计算机程序设计是学习计算机科学的基本技能。
算法以数据结构为核心,运用数学知识构建合适的模型,采用计算机程序设计语言编写程序,
解决实际问题,进行能力训练,培养兴趣,实现自我价值。

一级标准:
    了解什么是计算机程序,能够编写计算机程序解决简单的问题。
    1. 程序的基本结构
    2. 标识符与关键字
    3. 基本数据类型
    4. 变量和常量
    5. 算术表达式和关系表达式
    6. 整除,求余运算,常用数学函数
    7. 赋值语句,输入输出语句,复合语句,条件语句与循环语句(无嵌套)
 要求,
    1. 能用自然语言描述解决简单问题的方法和步骤
    2. 能用顺序、分支、循环语句编写完整程序
    3. 初步理解算法的意义。
 例题,
    求最小值和最大值。
    输入N个数,请找出这N个数中的最大值和最小值。
    输入数据,N+1行,第一行N,之后每行一个整数n(n<=1000)。
    输出数据,第一行,最下数,第二行最大数。
    
    用两个变量min 和 max 分别记录当前的最小最大值,然后用循环边读数,
    边将该数与 min 和 max 比较,每次都更新最大最小值。
    int min=1000;
    int max=-1000;
    int tep;
    std::cin >> N;
    for (int i=0; i<N; ++i)
    {
        std::cin >> tep;
        if(tep>max) max =tep;
        else if(tep<min) min=tep;
    }
 
 二级标准:
    了解什么是算法,能够用程序设计语言实现简单的算法,解决问题。
  知识要求,
    1. 逻辑表达式
    2. 条件嵌套,循环嵌套,数组。
    3. 枚举,简单排序,简单查找算法。
    4. 素数与合数,最大公约数,最小公倍数,互质数。
  能力要求,
    1. 能用简单枚举算法解决实际问题,能对数据进行简单排序和查找。
    2. 具备独立编写和调试简短程序的能力。
  例题,
    求一组N个数据中的第K小的数,并输出该值。
    输入数据,第一行 N,K,第二行,包含N个数,1个空格分割。
    输入数据,只有一行为第K小得数。
   
   先排序,再抽出第K个小的数。
   或者,选择排序,选择最小的,记录第K个就可以。
   
   
  三级标准:
    具有较强的程序实现能力,使用一种计算机程序设计语言编写程序解决问题。
   知识要求,
    1. 数制及其转化,信息编码,位运算。 
    2. 字符串类型。
    3. 子程序。
    4. 递归。
    5. 逻辑运算,整数的质因数分解,随机函数。
    6. 筛选法,欧几里得算法。
   能力要求,
    1. 全面掌握一种计算机程序设计语言。
    2. 具有运用简单数学知识编写程序解决问题的能力。
   例题,
    质因数分解
    思路,可先求出 N平方根内的素数 放入数组,然后用循环将N逐个整数数组中的素数,
    若能整除,则输出该素数。
   
  四级标准:
    了解几种常用的算法,运用这些算法编写程序,解决问题。
   知识要求,
    1. 结构类型,文件操作
    2. 数据类型的内在含义
    3. 贪心法,递推,回溯法,模拟运算
    4. 简单的字符串处理
    5. 集合以及集合运算,加法原理与乘法原理蛮简单的排列
   能力要求,
    1. 能根据实际问题选择合理的数据类型。
    2. 能运用贪心、递推、回溯、模拟等算法解决实际问题。
    3. 能独立设计简单的测试数据,测试自己的程序的正确性。
   
   例题,
    校门外的树
    长为L的马路上有一排树,每两颗相邻的树之间的间隔都是1米。
    我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置。
    数轴上的每个整数点,即0,1,2,3,...,L都种有一棵树。
    由于马路的一些区域(数轴上起终点(整数)表示)要用来修建地。
    区域的两端的树和内部的树都要移走,多个区域有可能有重叠。
    计算移走后还剩余多少树。
    
    输入文件 tree.in
    第一行L M,L表示马路长度,M表示区域数目
    之后M行,每行 起止点两个数据,表示要去除的区域
    
    输出文件 tree.out
    包含一个整数,表示马路上剩余的数的数目。
    
    思路,(模拟法) 统计区域范围直方图,最后bin有数据的(>=1),都需要被移除。
          为0的是能够保留与下来的树。
    
    
  五级标准:
    掌握简单数据结构知识,并结合已学算法和数学知识编写程序解决实际问题。
   知识要求,
    1. 指针类型;
    2. 一般线性表,队列,堆栈,二叉树的存储和遍历;
    3. 排列与组合,高精度数值处理;
    4. 二分算法,快速排序算法,深度优先搜索,宽度优先搜索,简单动态规划;
    5. 圆排列,可重集排列,鸽笼原理,素因数分解,幂函数,指数函数,对数函数,
       三角函数,模运算,不等式基础知识;
   能力要求,
    1. 能运用常用算法和人简单数据结构解决实际问题;
    2. 能从算法本质出发,分析相关算法之间的本质联系;
    3. 具备初级的数学建模能力;
   评价方法,
    NOIP普及组复赛中成绩排列全国前 40%
   
   试题:摆花,
    总共需要在店门口摆放m盆花。
    顾客最喜欢 n 种花,从1标号到n。
    规定第 i 种花,不能超过 ai盆,
    摆花时同一种花放在一起,且不同类的花按序号摆放。
    编程计算一共有多少种不同的摆花方案。
   输入数据 flower.in 共两行
    第一行包含两个 正整数 n 和 m,中间用一个空格隔开。
    第二行有 n 个整数,每两个整数中间 一个空格隔开,依次表示a1,...,an
   
   输出数据 flower.out
    共有一行,为方案数对1000007 取模(与取余类似,主要区别商的取整方向不同,导致负数结果不同)的结果
   输入输出样例
    flower.in
     2 4
     3 2
    flower.out
     2
    需要摆放4盆花,总共2种花,每种花不同超过3和2盆,
    有2种不同的摆花方案,1112 、1122
   数据范围:
    20%数据, 有 [0 n,m,ai 8]
    50%数据, 有 [0 n,m,ai 20]
    100%数据,有 [0 n,m,ai 100]
   
   参考题解,
    本题可采用 简单动态规划求解。
    设 f[i,j] 表示前i种花放在前j个花盆里的最大方案数(分解成小问题)
    那么,
     f[i,j] = sum(f[i-1,j-x]) 状态转移方程,类似卡尔曼滤波中的概念???
                              第i种花最少放0盆,最多放 min(ai,j),
                              第i种花本身限制为ai,
                              其次剩余需要摆放的盆数为j,两种取其最小值。
     也就是,第i 种花的摆放情况有 x =0,...,min(ai,j) 种,
     确定 第i 种花的情况后,原问题 退化成 多种情况下的小问题
     也就是 有i-1种花,需要摆放的 花盆总数为 j-x 
     (因为x是第i种花的不同方案,
     这样总花盆数减去 第 i种 花使用了的盆数 为子问题 需要摆放的花盆总数)
     
     边界条件,
        f[1,i]=1 (i <= a1)
        总共1中花,其本身限制为 a1,
        有i个花盆需要摆放,只能摆1种花,且 摆放的总数不能超过 a1限制条件
        
        
 六级标准:       
    掌握基本的数据结构知识,能够根据实际需求设计算法编写程序,解决问题。
   知识要求,
    1. 树、图的存储;
    2. 哈希表、集合数据结构;
    3. 图的最短路径、生成树算法,有向图的拓扑排序算法;
    4. 动态规划常见问题,分治策略,各种排序算法;
    5. 可重复组合,二项式定理,数列与级数,归纳与递推,
       容斥原理,函数的连续性、函数的单调性和极值;
   能力要求,
    1. 能够估计一些算法的时间复杂度和空间复杂度;
    2. 能根据实际问题的模型选择合适的算法和数据结构来解决实际问题;
    3. 具备知识收集和知识管理的能力;
   评价方法,
    提高组复赛前50%
   
   例题,
   题目描述
    C 国有 n 个大城市 和 m 条道路,每条道路连接这 n 个城市中的 某两个城市。
    任意两个城市之间最多只有一条道路直接相连。
    
    这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为 1 条。
    C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。
    但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。
    
    商人阿龙来到 C 国旅游。
    当他得知同一种商品在不同城市的价格可能会不同这一信息之后,便决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。
    设 C 国 n 个城市的标号从 1~ n,阿龙决定从 1 号城市出发,并最终在 n 号城市结束自己的旅行。
    
    在旅游的过程中,任何城市可以重复经过多次,但不要求经过所有 n 个城市。
    阿龙通过这样的贸易方式赚取旅费:
        他会选择一个经过的城市买入他最喜欢的商品――水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。
        由于阿龙主要是来 C 国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。
        
    假设 C 国有 5 个大城市,城市的编号和道路连接情况如下图,
    单向箭头表示这条道路为单向通行,双向箭头表示这条道路为双向通行。

    假设 1~n 号城市的水晶球价格分别为 4,3,5,6,1。
    阿龙可以选择如下一条线路:1->2->3->5,并在 2 号城市以 3 的价格买入水晶球,
    在 3号城市以 5 的价格卖出水晶球,赚取的旅费数为 2。
    阿龙也可以选择如下一条线路 1->4->5->4->5,并在第 1 次到达 5 号城市时以 1 的价格买入水晶球,
    在第 2 次到达 4 号城市时以 6 的价格卖出水晶球,赚取的旅费数为 5。
    现在给出 n 个城市的水晶球价格,
    m 条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。
    请你告诉阿龙,他最多能赚取多少旅费。
    
  输入输出格式
  
   输入格式:
    第一行包含 2 个正整数 n 和 m,中间用一个空格隔开,分别表示城市的数目和道路的数目
    第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这 n 个城市的商品价格。
    接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。
    如果 z=1,表示这条道路是城市 x 到城市 y 之间的单向道路;
    如果 z=2,表示这条道路为城市 x 和城市y 之间的双向道路。
    
   输出格式:
    输出文件 trade.out 共 1 行,包含 1 个整数,表示最多能赚取的旅费。
    如果没有进行贸易,则输出 0。
   
   输入输出样例
    输入样例,
    5 5 
    4 3 5 6 1 
    1 2 1 
    1 4 1 
    2 3 2 
    3 5 1 
    4 5 2 
    输出样例,
    5

    【数据范围】
    输入数据保证 1 号城市可以到达 n 号城市。
    对于 10%的数据,1≤n≤6。
    对于 30%的数据,1≤n≤100。
    对于 50%的数据,不存在一条旅游路线,可以从一个城市出发,再回到这个城市。
    对于 100%的数据,1≤n≤100000,1≤m≤500000,1≤x,y≤n,1≤z≤2,1≤各城市
    水晶球价格≤100。
    
[解题思路] 
    本题很直观的就是想找到一个价格最低和一个价格最高点(满足由起点能到达,且又可顺序到达终点),
    找最低价格的点可以这样来处理,从源点开始找到所有点的最低价格(
    某个顶点的最低价格就是从源点到该所有可能路径上的价格最低的点),
    最后枚举卖出的点,并且判断该点是否可以到达即可。
    此外,由于数据规模较大,一般的邻接矩阵难以承受,因此采用动态数据结构邻接表。
    但是本题有环,处理时还有几个细节问题: 
    1.由于是最后要判定所有的顶点是否可以到达终点,因此不妨将所有的边反向,
       由终点出发判断终点可以到达那些顶点就可以了,并做上标记。
       这样也就要求在读入边的时候必须反向再储存一次。 
    2.用SPFA求某个顶点的最低价格时,对SPFA进行了改进。
       由SPFA的原理可以知道,该算法可以处理环的问题,
       但是要求最短路径的长度是可以收敛的,也就是说不能在图中存在负权。该题目满足此要求。
       SPFA是用来求最短路径的算法,在此对其改进,来求路径上最小价格的点 .

  这题题意要求我们求出能赚取的最大差价。说到差价很好想了,肯定是卖出价-买入价=差价。
  题目规定了从点1出发到点n,我的做法是,
  从起点正向跑一次spfa,可以求出所有的买入价的最小值。
  然后从终点反向跑一次spfa,可以求出所有卖出价的最大值。最后维护一下最大差价便是答案。
  稍微想一下便能发现这个算法正确性是显然的。至少我这么认为。
  建图的时候有单向边有双向边,判断一下就好了。

  这道题的解法比较多,不过大多是基于动态规划的,,这里提两种算法。。

  算法1:我们要维护的东西是从1走到i点时的最小价格和最大价格,,但是每个城市可以经过多次,
    我们自然会想到强联通分量。求出强联通分量之后,缩点,对每一个强联通分量记录一个内部的最大价格和最小价格用于更新答案。
    这样整个图就变成了一个有向无环图,我们利用拓扑序进行DP即可。
    f[i]表示i点卖出的最大获利,min[i]表示走的i点的最小价格。
    注意卖出点一定要在买入点之后,所以最大获利不一定是在n点卖出,所以我们取答案时要找每个点卖出的最大值,或者在DP过程中直接更新。
    另外可能有一些点可以到达n但是从1出发到达不了(数据太弱没有这种情况),这些点在拓扑DP之前要处理掉,
    或者我们用记忆化搜索就可以避免这个问题了。
    
  算法2:对每个点维护一个minp[i],maxp[i],表示到达i点的最小和最大价格,我们用spfa来完成这个信息的更新。
    同样卖出点一定要在买入点之后,所以我们先做一遍正向spfa更新最小,
    再做一遍反向spfa更新最大,这样就可以保证minp是在maxp的前面的了。
    也可以像算法1那样,只做一遍正向spfa,只记录最小,最后取每个点(a[i]-minp[i])的最大值即可。
    这个思想很有用,说明spfa可以消除动态规划的暂时后效性。

参考

七级标准:
    综合运用算法和数据结构编写程序,解决问题。
  知识要求,
    1. 并查集、线段树、哈夫曼树、二叉排序树、二叉堆;
    2. 图的连通性算法,最短路、最小生成树的优化算法,
       二分图的构造、判定以及匹配,搜索算法的优化,扩展欧几里德算法;
    3. 中国剩余定理,剩余类,概率基础知识,解析几何基础知识;
  能力要求,
    1. 能根据算法的 时间和空间复杂度的要求 灵活构造算法和数据结构解决实际问题;
    2. 具备较强的程序代码实现能力;
    3. 具备较强的归纳、总结和表达能力;
  评价方法,
    NOIP提高组复赛 前 20%
  
  例题,关押罪犯
   题目描述,
    S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。
    很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。
    我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。
    如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件。
    
    每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。
    公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
    
    在详细考察了N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。
    他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。
    假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。
    
    那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?

  输入输出格式
  输入格式:
    输入文件的每行中两个数之间用一个空格隔开。第一行为两个正整数N 和M,
    分别表示罪犯的数目以及存在仇恨的罪犯对数。
    接下来的M 行每行为三个正整数aj,bj,cj,表示aj 号和bj 号罪犯之间存在仇恨,其怨气值为cj。
    数据保证1<aj=<=bj<=N ,0 < cj≤ 1,000,000,000,且每对罪犯组合只出现一次。

   输出格式:
    共1 行,为Z 市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出0。

 输入输出样例
   输入样例#1:
    4 6
    1 4 2534
    2 3 3512
    1 2 28351
    1 3 6618
    2 4 1805
    3 4 12884
   输出样例#1:
 
  【输入输出样例说明】
    罪犯之间的怨气值如下面左图所示,
    右图所示为罪犯的分配方法1,4分配在一起,2,3分配在一起
    市长看到的冲突事件影响力是3512(由2 号和3 号罪犯引发)。
    其他任何分法都不会比这个分法更优。

 【数据范围】
   对于30%的数据有N≤ 15。
   对于70%的数据有N≤ 2000,M≤ 50000。
   对于100%的数据有N≤ 20000,M≤ 100000。
    
   分析:
    最大值最小,很显然,这题可以用二分法,排序之后发现可以用 贪心做,因为要使最大值最小,
    排序后这个最大值是存在的,怎么让它最小呢?对于会冲突的两个罪犯,我们连一条无向边,
    按权值从大到小排序,从大到小枚举每一条边,如果边上的两个罪犯已经在一个监狱,
    那么输出结果,否则将两个罪犯放到不同的监狱.那么怎么实现呢?
    集合的这些操作可以用一个非常方便的数据结构完成----并查集,
    如果a和b不在一个监狱,b和c不在一个监狱,那么a和c一定在一个监狱,
    对此,我们将并查集的大小扩大一倍,来建立罪犯的补集,即不在同一个监狱的罪犯的集合.3512


八级标准:
    掌握高级数据结构知识,能运用恰当算法编写程序,解决较复杂问题。
  知识要求,
    1. 树状数组,字典树,优先队列,平衡树;
    2. 网络流算法,复杂的分治思想,树形动态规划,
       状态压缩动态规划,二分图的匹配,启发式搜索
    3. 矩阵概念及其基本运算,线性方程组的解法,迭代法,
       费马小定理和欧拉定理,母函数。
  能力要求,
    1. 能针对复杂问题建立清晰的数学模型;
    2. 能运用数学知识、高级数据结构和算法解决复杂的问题;
    3. 能根据需要,开展基于协作的学习和研究;
  评价方法,
    NOI铜牌累计积分 250分 以上。
  
  例题,能量采集 
   题目描述,
    栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。
    在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。
    栋栋的植物种得非常整齐,一共有n列,每列有m棵,植物的横竖间距都一样,
    因此对于每一棵植物,栋栋可以用一个坐标(x, y)来表示,其中x的范围是1至n,
    表示是在第x列,y的范围是1至m,表示是在第x列的第y棵。
    
    由于能量汇集机器较大,不便移动,栋栋将它放在了一个角上,坐标正好是(0, 0)。
    能量汇集机器在汇集的过程中有一定的能量损失。
    如果一棵植物与能量汇集机器连接而成的线段上有k棵植物,则能 量的损失为2k + 1
    例如,当能量汇集机器收集坐标为(2, 4)的植物时,由于连接线段上存在一棵植物(1, 2),会产生3的能量损失。
    注意,如果一棵植物与能量汇集机器连接的线段上没有植物,则能量损失为1。现在要计算总的能量损失。
    下面给出了一个能量采集的例子,其中n = 5,m = 4,一共有20棵植物,
    在每棵植物上标明了能量汇集机器收集它的能量时产生的能量损失。

   在这个例子中,总共产生了36的能量损失。
   
    输入格式
        仅包含一行,为两个整数n和m。

    输出格式:
        仅包含一个整数,表示总共产生的能量损失。

    输入输出样例
        输入样例#1:
        5 4
        输出样例#1:
        36

        输入样例#2:
        3 4
        输出样例#2:
        20

    说明
    对于10%的数据:1 ≤ n, m ≤ 10;
    对于50%的数据:1 ≤ n, m ≤ 100;
    对于80%的数据:1 ≤ n, m ≤ 1000;
    对于90%的数据:1 ≤ n, m ≤ 10,000;
    对于100%的数据:1 ≤ n, m ≤ 100,000。

参考题解

九级标准:
    具有对问题进行抽象和数学建模能力,
    能选用合适的数据结构和算法编写程序,解决较难问题。
  知识要求,
    1. 块状链表,后缀数组,后缀数,复杂的线段树;
    2. 动态规划优化,模拟退火算法;
    3. 计算几何知识(点积、叉积、凸包、半平面等知识以及应用),数学期望;
  能力要求,
    1. 能针对疑难问题建立清晰的数学模型;
    2. 能灵活运用数学知识、高级数据结构和算法解决疑难问题;
    3. 具备发现问题、解决问题的探索研究能力;
  
  评价方法,
    NOI银牌 或 累计积分 500分以上的选手
  
  试题,直线和点
    平面的n条直线将平面分割成了若干区域,给出m个点,求每个点所在区域的面积。
    为了防止出现面积无穷大的情况,有额为的四条直线框定了平面区域的大小,
    分别是x=L,y=L,x=-L,y=-L。其中L是给定的正实数,所有的点都在这个框定的区域内
    另外为了防止精度问题,任意一个点到任意一条直线的距离>10^-7。

 输入数据:
    输入文件名为line.in。
    第一行两个正整数和一个正实数,n,m,L,意义如上所述。
    第2~n-1行每行三个实数A,B,C表示直线的方程为Ax+By+C=0。 第n+2~n+m+1行每行两个实数x,y表示点的坐标。

 输出数据:
    输出文件名为line.out。
    按输入的顺序输出每个点所在的区域面积,每个一行,保留2为小数。 

 输入样例:
    2 4 3
    1 1 -1
    -1 1 -1
    0 2
    -2 1
    2 1
    0 0

 输出样例:
    4.00
    8.50
    8.50
    15.00

 数据范围:
    对于20%的数据,n,m<=10。
    对于40%的数据,n,m<=300。
    对于100%的数据,n<=500,m<=100000。
    对于100%的数据,输入数据的绝对值<=10^7且最多保留2位小数

十级标准(NOI金牌)
    具有一定的提出问题、解决问题的研究能力,能构造算法与数据结构,解决开放性问题。

  知识要求:
    1、 最小树形图,自动机,动态树,树套树,一般图的匹配。
    2、 双重动态规划,基于连通性的动态规划,线性规划,极大极小搜索算法。
    3、 三维计算几何,组合游戏中的NIM问题和SG函数,群的概念,
        置换群,Burnside引理,Polya原理,莫比乌斯反演定理,FFT。

  能力要求
    1、 具备创造性地运用数据结构和算法解决开放性问题的能力。
    2、 具备很强的代码编写能力。
    3、 具备提出问题、并开展相关研究的创新能力。

  题例:
    试题名:管道取珠
    详见NOI2009

参考

posted @ 2024-08-23 15:16  梁君牧  阅读(52)  评论(0编辑  收藏  举报