全国站

热门城市 | 全国 北京 上海 广东

华北地区 | 北京 天津 河北 山西 内蒙古

东北地区 | 辽宁 吉林 黑龙江

华东地区 | 上海 江苏 浙江 安徽 福建 江西 山东

华中地区 | 河南 湖北 湖南

西南地区 | 重庆 四川 贵州 云南 西藏

西北地区 | 陕西 甘肃 青海 宁夏 新疆

华南地区 | 广东 广西 海南

资    源
  • 资    源
当前位置:查字典高考网>高中频道>信息学联赛辅导>信息学联赛辅导:全面考虑问题

信息学联赛辅导:全面考虑问题

来自:查字典高考网 2009-11-12

在编程序时常常会遇到这样的问题:一道很简单的题目,编出的程序却错了很多测试点。这其中的主要原因是由于考虑问题不全面,只想到了一些普通的情况,而遗漏了很多特殊的地方。

下面通过几个例子来进行讨论。

1.项链(IOI'93第一题)

由n(n100)个珠子组成一个项链,珠子有红、蓝、白三种颜色,各种颜色的珠子的安排顺序由输入文件任意给定。

图1.1可看作由字符b(代表蓝色珠子)和字符r(代表红色珠子)所组成的字符串。假定从项链的某处将其剪断,把它摆成一直线,从一端收集同种颜色珠子(直到遇到另一种颜色的珠子时停止)。然后再从另一端重复上述过程(请注意,这一端珠子的颜色不一定和另一端珠子的颜色相同)。

brbrrrbbbrrrrbrrbbrbbbbrrrrb

图 1.1

请选择项链被剪断的位置,目标是使两端各自颜色相同的珠子数目之和最大。例如,对于上图(只有红蓝两种颜色),最大值M是8,断点位置在珠子9和珠子10之间,或珠子24和珠子25之间。

项链中可以有三种颜色用b(蓝)、r(红)和w(白)表示。白色既可看成是红色,又可看成蓝色。

(1)一个ASCII文件NECKLACE.DAT中的内容:该文件中每一行代表某个项链中各种颜色珠子的配置。把输出内容写入ASCII输出文件NECKLACE.SOL中。

作为举例,输入文件的内容可以是:

brbrrrrbbbbrrrrrbbrbbbbrrrrb

bbwbrrrwbrbrrrrb

(2)对于给定的每个项链的配置,求出收集到的珠子数的最大值M及相应的断点位置(注意可能存在多个位置)。

(3)在输出文件NECKLACE.SOL中写入收集到的珠子数的最大值M及断点位置。

例如:

brbrrrbbbrrrrrbbrbbbbrrrrb

8 between 9 and 10

bbwbrrrwbrbrrrrrb

10 between 16 and 17

作为竞赛的第一题,这道题目显然是比较简单的题目。它只包含两个步骤:剪断项链和收集同颜色的珠子。例如下面的一条项链(a)从N=3处断开变为项链(b)。这个操作只需要将前N个珠子移到后边即可。

brb | rrwb ------ rrwbbrb

(a) (b)

现在只剩下收集同颜色的珠子这一步,根据上面的例子我们很容易写出下面的程序。

用变量c来记录最左边珠子的颜色;

Left:=0;

FOR i:=1 TO 项链长度 DO

IF 左数第i个珠子的颜色与c相同

THEN Inc(Left)

ELSE Break;

这样变量Left中存放的就是从左边收集到的珠子的数目,同理可求得从右边收集到的珠子的数目Right,则所求的值为Lett+Right。这个程序显然能通过上面的例子,由于这是一道简单的题目,谁也不想在它上面多费时间,往往做到此为止。可是如果仔细想想,再举几个例子,就会发现错误。上面的那条项链断开后左有两个珠子为红色和蓝色,在题目中这两种颜色的珠子都比较普通,只有白色的珠子比较特殊。所以应举一个断开后左右两端有白色珠子的例子。还是上面那条项链入N=6处断开。

brbrrw| b-------bbrbrrw

正确答案应是收集到5个珠子:左边2个,有边3个。而上面的程序得到的结果却是3个:左边2个,右边1个。错误就在于没有考虑到左右两端有白色珠子的情况。一种较容易的解决方案是先将左有两端的白色珠子均取下,记其数目为Other,再用上面的程序来求,结果为Left十Right十Other。我们解决了左右两端出现白色珠子的情况,还有没有别的特殊情况呢?一个真正特殊的项链不应包含所有颜色的珠子,最好只包含一种颜色。如下面的项链是由l0个红色的珠子组成。

rrrrrrrrrr

用我们的程序得出的结果是20个,显然是不对的。因为题目中要求是收集珠子而不是数珠子,所以最后得到的总数不应超过珠子的总数。这虽然只是一个字眼的问题,却使当年中国队的选手失了不少分。一个简单的改正措施是判断最后的结果是否大于珠子总数,如果是则输出珠子的总数即可。

虽然项链这道题比较简单,却很难简单地得到满分,最容易出的错误就是考虑的不全面。

2.多项式加法

由文件输入两个多项式的各项系数和指数,编程求出它们的和,并以手写的习惯输出此多项式。

要求:

(1)多项式的每一项axb用axb的格式输出。

(2)两个多项式在文件中各占一行,每行有2m个数,依次为第一项的系数,第一项的指数,第二项的系数,第二项的指数

例如输入文件为:

l 2 3 0

-l 1

输出:

x2-x+3

此题是一道大学生竞赛的题目,很多人只用了很短的时间就编出程序。但最后测试的结果却令他们很惊讶:通过的数据还不到一半!他们犯的错误归根结底就是考虑得不够全面。

此题对于多项式相加的过程很简单,只要找出幂次相同的项相加即可。关键在于题目中要求用符合手写的习惯输出结果。何为手写的习惯呢?例如多项式3x2-x中就有很多手写的习惯。我们不会将其写成3x2一lx1+O。因为首先当某项系数为1时,我们习惯于不写系数;其次对于一次项我们也要省略指数;还有我们从来不写出系数为0的项。一个简单的多项式就有这么多的手写习惯,我们已经感觉到了要把这题全面地做出很不容易。虽然我们平时总在写多项式,但是谁也不会留心我们写多项式时的习惯。我们写多项式的习惯究竟有哪些呢?

(1)首先我们考虑对于多项式中的任一项axb它有多少手写习惯:

当a=0时,此项省去不写; 当a=l时,省去a; 当a=-1时,系数只写一个负号'-'; 当b=0时,省去x和b; 当b=l时,省去b; 当a一1时,省去此项前面的加号(首项除外)。

我们一口气写了这么多条规则,每一条看起来都很正确,但合在一起是否还正确呢?当a=l或-1时要省去其中的数字1,这是针对一般情况而言。如果b=0,则数字1就不应当省去。所以我们不仅要单独考虑a和b,而且要将其和起来考虑。

(2)其次对于整个多项式有哪些规则呢?

多项式的首项系数前不应有加号'+'; 如果一个多项式为零多项式,则应写出数字'0'。

现在看起来这道题并不是一道很容易的题目。它需要一个人在很短的时间内能全面地总结出上述那么多规则。这对一个人的全面考虑问题的能力是一个很好的检验。

3.求最长的公共子串(NOI'93第一题)

求N个字符串的最长公共子串,N20,字符串长度不超过255。例如N=3,由键盘 依次输入3个字符串为

What is local bus ?

Name some local buses.

local bus is a high speed I/O bus close to the processor.

则最长公共子串为local bus。

此题也是作为第一题出现,同样有很多入在此题上失分。我们都做过求n个数最大公 约数的问题,在那道题中求3个数的最大公约数时,可以先求两个数的最大公约数,再将此数与第三个数求一次最大公约数。有人从那道题中得到启发,设s(p,q)为字符串p 和q的最长公共子串,则p、q、r的最长公共子串为s(s(p,q),r)。这样只需编写一个求两个字符串的最长公共子串的过程即可。但这种方法对不对呢?看看下面的例子。

三个字符串分别为'abc'、'cab'、'c',则s(p,q)='ab',s(s(p,q).r)=''。事实上这三个字符串有公共子串'c'。显然上面的算法是错误的,原因在于没有考虑到本题与求最大公约数那道题在性质上的不同之处。最大公约数可以由局部解得到全局解,而本题却不能。正确的做法是列举出其中一个字符串的所有子串,找出其中最长的而且是公共的子串。

FOR i:=l TO 第一个字符串的长度 DO

FOR j:=i TO 第一个字符串的长度 DO

IF (第i个字符到第j个字符的子串为公共子串)AND(j-i+1当前找到的最长公共子串的长度max)

THEN

BEGIN

max:=j-i+l;

最长公共子串:=此子串;

END;

为了提高效率,我们可以将最短的字符串作为第一个字符串。此题需要考虑的并不像多项式加法那道题那么多,但是它提醒我们在不清楚题目的性质之前,不能滥用以前的方法。

4.可重复排列(NOI'94第一题)

键盘输入一个仅由小写字母组成的字符串,输出以该串中任取M个字母的所有排列及排列总数(输入数据均不需判错)。

此题是由全排列问题转变而来,不同之处在于:一个字符串中可能有相同的字符,导致可能出现重复的排列。例如从字符串'aab'中取2个字符的排列只有三种:'aa'、'ab'、'ba'。如何去掉那些可能重复的排列呢?一种想法就是每产生一种不同的排列就记录下来,以便让以后产生的排列进行比较判重。这种想法显然没有考虑到随着字符串长度的增加,排列将会多得无法记录,而且这种判重方法在效率上也会很低。最好有一种方法能在产生排列的过程中就能将重复的去掉。先看一看全排列的递归过程

PROCEDURE Work(k);

BEGIN

IF k=m+l THEN 打印结果

ELSE FOR i:=1 TO 字符串长度n DO

IF (ie[l],e[2],e[k-1]) THEN

BEGIN

e[k]:=i;

Work(k+l);

END;

让我们来分析产生重复的原因。考虑从字符串。'aab'中取2个字符的排列。当e[1]从l变到2时,字符串中的字符却没有变,都是'a'。这样我们只要在改变e[k]时,判断其对应的字符是否也改变。即在上面的过程的循环中加一句判断(设字符串为s):IF s[i] s[e[k]] THEN 这当然只是一个粗略的想法,我们仅仅用上面的例子就能发现问题: 程序在对e[k]的每一次赋值之前都要进行一次判断,而不是我们预想的在改变e[k]时才进行判重。我们用一个布尔型的局部变量First来记录是否是对e[k]进行第一次赋值。修改后的程序如下:

PROCEDURE Work(k);

BEGIN

First:=True;

IF k=m+l THEN 打印结果

 

ELSE FOR i:=1 TO 字符串长度n DO

IF (ie[l],e[2],e[k-1]) THEN

BEGIN

First:=false;

e[k]:=i;

Work(k+l);

END;

END;

很多选手的程序到此就为止了,可是它还有一个致命的错误:我们在判重时假定这个字符串中的字符已经排好顺序,即相同的字符已经连在一起。事实上并不是这样,输入的字符串中的字符排列是任意的,需要我们在递归之前作一次排序的初始化才能保证程序运行得正确。可见虽然本题的难点是在递归过程中,但是那些简单的初始化却是程序最容易忽略,最容易出错的部分。

5删除多余括号(IOI'94国家队选拔赛第一题)

键盘输入一个含有括号的四则运算表达式,可能含有多余的括号,编程整理该表达式,去掉所有多余的括号,原表达式中所有变量和运算符相对位置保持不变,并保持与原表达式等价。

例:输入表达式

a+(b+c)

(a*b)+c/d

a+b/(c-d)

应输出表达式

a+b+c

a*b+c/d

a+b/(c一d)

注意输入a+b时不能输出b+a。

表达式以字符串输入,长度不超过255。输入不要判错。

所有变量为单个小写字母。只是要求去掉所有多余括号,不要求对表达式化简。

同多项式加法一样,此题要求的也是一个我们平时很习惯但却没有注意的规则:去掉多余的括号。哪些括号是多余的呢?这要根据紧挨着括号前后的运算符号和括号中最后一个运算符号来决定。例如表达式a+(b*c+d)-e中,括号前的符号为+,括号后的符号为-,括号中最后一个运算符号为+,所以括号是多余的。总结括号中最后一个运算符号为+、-、*,/时,括号前、后为何运算符号时括号是多余的,我们很容易得出表1.1。

表1.1 多余的括号满足的条件

括号前的符号

括号中的符号

括号后的符号

+

+

+、-

+

-

+、-

+、-、*

*

+、-、*、/

+、-、*

/

+、-、*、/

 

上表只是对一般情况的分析,显然是很不全面的。首先括号前,括号中和括号后都可能无运算符号,例如表达式((a))+b;其次变量前还可能带有负号,例如表达式(-a)+ (-b)中的括号一个是多余的,一个不是多余的。还有一些其它的情况如表达式只有括号无任何变量等需要考虑。此题留给大家自己去完成。注意多用一些特殊的数据来测试自己的程序。大家也可以试着用表达式树的方法来做此题。

6.合并表格(NOI'93第二题)

在两个文本文件中各存有一个西文制表符制成的未填入任何表项的表结构,分别称之为表1和表2,要求编程将表1和表2按下述规则合并成表3。

规则:表1在上表2在下,表1与表2在左边框对齐,将表1的最底行与表2的最顶行合并。

例如,3张表见图1.2。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

表1

表2

表3

图1.2

编程要求:

(l)程序应能从给定的文本文件中读入两个源表并显示。

(2)若源表有错,应能指出其错(错误只出在表1的最底行和表2的第一行)。

(3)将表1和表2按规则合并成表3,并显示之。

(4)所有制表符的ASCII码应由选手自己从给出的示例文件中截取。

我们把此题的分析留给读者去独立完成。

千里之堤,毁于蚁穴。一些程序往往不是错在算法上,而是错在考虑得不全面上。希望通过以上几个例子,能使大家对此引起重视,在以后的编程中多加注意,避免不应有的遗憾。

 

【信息学联赛辅导:全面考虑问题】相关文章:

2007年四川高中数学竞赛预赛试题

信息学联赛辅导:语言概述与预备知识

2007年高中数学联赛四川赛区初赛试题参考答案及评分标准

高中数学联赛培训讲义(二)

清华大学2008年文化艺术冬令营相关问题说明

哪些知识点是高中联赛中重点考查的?

信息学联赛辅导:NOI评测环境及对编程语言使用限制的规定

新课改“保底不封顶” 课外辅导面临新课题

政协委员建议:北京高中课改可考虑跨校选修

信息学联赛辅导:Fillchar过程全解

[标签:竞赛联赛,学习方法]

网友关注

高考状元总结高考英语学习的五大妙法

2016年消除高考考前恐慌的4点建议

重庆三峡职业学院以赛促教 全国技能大赛屡结硕果

高考考生最常见意外状况 忘记填姓名怎么办

家长的陪伴鼓励才是高考生最需要的“高考房”

老师经验谈高三考生如何在考试中避免粗心

2016高考复习:能明显增加高考分数才是有效备考

中国农业大学举办《习近平谈治国理政》读书分享会

2016年考生如何预防和治疗高考复习综合症

学霸教你练就超强高考解题能力

总结2016年高考考场需注意的16个细节

12种解答高考数学题的方法总结

兰大校长:曾有院校专人驻守在周边宾馆“挖人”

2016年北大光华管理学院本科招生常见问题解答

考生2016高考复习如何利用最短时间解决错题

如何使高三生同时做到补弱科和增强科

2016高考提醒:别让“高考房”扰乱孩复习心态

王乘:教学与科研的关系是大学的根本问题

高考招生引入综合评价效果如何?

备战2016年高考各个科目考场注意事项

40条2016高考过来人整理的重要经验

专家指导高考前备考要慢复习少做题

经验分享:高三考生需要注意的18件事

北大学姐经验分享每个牛人都是蜗牛

2016高考考场经验介绍:如何应付好数学考试

高考学长分享2016年高考复习建议

名师指导2016年高考复习攻略

北京大学上演原创音乐剧《元培校长》

2015-2016高考试题作答要确保效率

南京夫子庙六景点昨免费开放 考生家长前来祈福

网友关注视频

葛军大爷怒了:高考我出了个小学数学送分题,你们跟我说不会做?

高考作文:全国2卷 材料作文破题分析 2019高考助力

2019年高考试卷解析,数学套路不好用了

老马讲高考真题第九季2018年高考地理新课标一卷第37题

amc传媒音乐影像 第一季 第600集 高中校长演唱《记忆花园》为高考学子助力打气

2019高考数学全国2卷理科第16题视频讲解及答案

他高考作文仅得6分,总分428分,被985高校录取,却被导师拒绝!

儿子高考英语没考,上了西京交大,老爸忍不了:复读!上清华!

学渣儿子高考,英语选择题全选B!老师通报成绩的那一刻父亲懵了

视频|上海高考作文: 寻找“中国味” 专家

高中语文知识清单高考语文总複习工具书第5次修订五全綵版五三曲一线科学备考基础知识手册知识大集结资料书参考书导书高一高二高三

老师好:这大概是高考前所有班主任都会干的事,取消一切副课!

1000张学生用草稿纸考研专用免邮空白便宜薄演草演算纸白纸本书写纸批发打草a4大张实惠装18k高考数学草稿本

2019年高考数学全国2卷理科第4题讲解及答案

高级中学高考试卷分析专题教研评比活动

沈阳音乐学院郎亦农教授的女高音高考曲目解析课程 第9集 《赛吾里麦》演唱讲解,音乐表现一定要自然流畅

视频|2019全国高考今日开考: 语文特级教师评析上海卷高考作文

高考前必听的5首励志歌曲,《Dream it possible》最能鼓舞人心!

凤凰县高级中学高考试卷分析专题教研会

体育生参加高考,太猛了,第一名是飞起来了吗?

爆笑班主任 第一季 第220集 高考前最后一只视频,山东王老师揭秘高考的秘密

探秘历史 第二季 第233集 考英语用来睡觉,结果仍是高考状元,如今她怎么样了?

这四首励志歌曲,送给为梦起航的高考学子们,听完心潮澎湃!

优秀!英语数学双满分,广西“最牛”高考状元730分刷新最高纪录

高职高考数学公式

看懂图片,你也会做高考地理题,解析2019年高考文综地理4

2019高考数学第四题技巧秒出答案

知道班里的高考成绩后,山东班主任气吐血了

凤凰县高级中学高考试卷分析专题教研会

这!就是专业 第15集 中国矿业大学——数学专业