全国站

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

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

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

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

华中地区 | 河南 湖北 湖南

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

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

华南地区 | 广东 广西 海南

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

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

来自:查字典高考网 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码应由选手自己从给出的示例文件中截取。

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

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

 

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

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

中国传媒大学2008年报考艺术专业诸问题回答

信息学联赛辅导:新《标准》下的信息技术教育课

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

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

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

全国青少年信息学奥林匹克竞赛联赛试题大纲

2007年全国高中数学联赛(吉林赛区)预赛试题与答案

2007年全国高中数学联赛(吉林赛区)预赛试题

高二数学联赛讲座三角函数及其最值(一)

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

网友关注

手机风暴席卷中小学 家长应注意引导

家长必读:高三家长不能犯的20个忌讳

家长学堂:当百依百顺的孩子变得我行我素

知名博主推荐:爱的教育就是素质教育

教育专家:建议家长给予孩子的十大礼物

家长必读:2012届高三家长要做好四件事

家长教育经验分享:每天只问女儿4句话

“虎爸”的苦恼:儿子未进名校父亲跳天桥

家长必读:利于父母与孩子沟通的几种有效方法

家长必读:培养孩子自我教育能力的策略及途径

家长心得:树立父母威信的九字真经

家长深思:因材施教 兔子为奔跑而生

家长必读:高三家长做一个好的诱导者

家长深思:到底是喜欢孩子还是分数

高中家长周末可以为孩子做点什么

家庭教育:中国家长为何太紧张

家长必读:帮助孩子训练记忆力的好方法

专家建议:教育好孩子家长必做的十件事

高三家长必读:三方面呵护缺一不可

家长课堂:莫吝啬鼓励 学会表扬孩子

家长教育心得:父母不要和逆反的孩子较劲

家长必读:成为好父母的7个秘笈

高三家长应该如何与各科老师进行有效沟通

家长学堂:对孩子的表扬要视情况而定

专家指导:给高三家长的七点忠告

专家支招:如何在高招咨询会上进行提问

家长学堂:九招培养孩子过硬的心理素质

过来人考妈分享:怎样帮助落后的孩子圆梦北大

经验分享:高三家长应让孩子尽量参与自主招生

高三生必读:考生三大心态 决定高考成绩成败

网友关注视频

高职高考数学公式

印度美术高考美术联考,考前培训班

如何制作100万层的酥皮糕点?推算过程像数学高考题

探秘历史 第二季 第211集 此人高考数学考了0分,因作文写3句话被重点大学录取

北京新闻 2019 5.9万余北京考生今日高考 语文试题鼓励创造性阅读与表达

最新高考数学全国2第12题视频讲解及答案

一站到底:高考语文老师上台,穿长衫说Rap,全场笑翻了!

女儿高考作文只得5分,怎料妈妈一听作文题目,瞬间懂了

高中数学必修5 高考数列选填真题技巧秒杀讲解

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

励志歌曲《阳光总在风雨后》送给高考的莘莘学子,祝金榜题名!

美术联考用纸上海考试模拟试卷纸高考统考纸 4k水粉纸素描纸 速写纸卡纸美术模拟测试试卷纸 美术考试专用纸

你高考成绩高吗?这道题目怎能成立?高难度奥数,能不能把你难住

这!就是专业 第18集 中国科学技术大学

男孩考上理想大学,却因为网瘾休学在家,高中班主任上门劝导

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

这!就是专业 第47集 江苏理工学院

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

盘点今年最难的高考数学题

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

沈阳音乐学院郎亦农教授的女高音高考曲目解析课程 第1集 沈阳音乐学院郎亦农为你讲解女高音高考曲目

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

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

2019 广西:帅气学霸高考730分 数学英语满分!

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

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

2019全国高考志愿填报攻略 第50集 天津市高考历史三年本科录取排名

加油吧考生:2019高考咨询大直播 第43集 科学填报志愿 规划精彩人生

评测今年的高考语文卷

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