全國(guó)

        熱門(mén)城市 | 全國(guó) 北京 上海 廣東

        華北地區(qū) | 北京 天津 河北 山西 內(nèi)蒙古

        東北地區(qū) | 遼寧 吉林 黑龍江

        華東地區(qū) | 上海 江蘇 浙江 安徽 福建 江西 山東

        華中地區(qū) | 河南 湖北 湖南

        西南地區(qū) | 重慶 四川 貴州 云南 西藏

        西北地區(qū) | 陜西 甘肅 青海 寧夏 新疆

        華南地區(qū) | 廣東 廣西 海南

        • 微 信
          高考

          關(guān)注高考網(wǎng)公眾號(hào)

          (www_gaokao_com)
          了解更多高考資訊

        首頁(yè) > 高中頻道 > 信息學(xué)聯(lián)賽輔導(dǎo) > 信息學(xué)聯(lián)賽輔導(dǎo):全面考慮問(wèn)題

        信息學(xué)聯(lián)賽輔導(dǎo):全面考慮問(wèn)題

        2009-11-12 22:55:59網(wǎng)絡(luò)

         

        在編程序時(shí)常常會(huì)遇到這樣的問(wèn)題:一道很簡(jiǎn)單的題目,編出的程序卻錯(cuò)了很多測(cè)試點(diǎn)。這其中的主要原因是由于考慮問(wèn)題不全面,只想到了一些普通的情況,而遺漏了很多特殊的地方。
        下面通過(guò)幾個(gè)例子來(lái)進(jìn)行討論。
        1.項(xiàng)鏈(IOI'93第一題)
        由n(n≤100)個(gè)珠子組成一個(gè)項(xiàng)鏈,珠子有紅、藍(lán)、白三種顏色,各種顏色的珠子的安排順序由輸入文件任意給定。
        圖1.1可看作由字符b(代表藍(lán)色珠子)和字符r(代表紅色珠子)所組成的字符串。假定從項(xiàng)鏈的某處將其剪斷,把它擺成一直線,從一端收集同種顏色珠子(直到遇到另一種顏色的珠子時(shí)停止)。然后再?gòu)牧硪欢酥貜?fù)上述過(guò)程(請(qǐng)注意,這一端珠子的顏色不一定和另一端珠子的顏色相同)。
        brbrrrbbbrrrrbrrbbrbbbbrrrrb
        圖 1.1
        請(qǐng)選擇項(xiàng)鏈被剪斷的位置,目標(biāo)是使兩端各自顏色相同的珠子數(shù)目之和最大。例如,對(duì)于上圖(只有紅藍(lán)兩種顏色),最大值M是8,斷點(diǎn)位置在珠子9和珠子10之間,或珠子24和珠子25之間。
        項(xiàng)鏈中可以有三種顏色用b(藍(lán))、r(紅)和w(白)表示。白色既可看成是紅色,又可看成藍(lán)色。
        (1)一個(gè)ASCII文件NECKLACE.DAT中的內(nèi)容:該文件中每一行代表某個(gè)項(xiàng)鏈中各種顏色珠子的配置。把輸出內(nèi)容寫(xiě)入ASCII輸出文件NECKLACE.SOL中。
        作為舉例,輸入文件的內(nèi)容可以是:
        brbrrrrbbbbrrrrrbbrbbbbrrrrb
        bbwbrrrwbrbrrrrb
        (2)對(duì)于給定的每個(gè)項(xiàng)鏈的配置,求出收集到的珠子數(shù)的最大值M及相應(yīng)的斷點(diǎn)位置(注意可能存在多個(gè)位置)。
        (3)在輸出文件NECKLACE.SOL中寫(xiě)入收集到的珠子數(shù)的最大值M及斷點(diǎn)位置。
        例如:
        brbrrrbbbrrrrrbbrbbbbrrrrb
        8 between 9 and 10
        bbwbrrrwbrbrrrrrb
        10 between 16 and 17
        作為競(jìng)賽的第一題,這道題目顯然是比較簡(jiǎn)單的題目。它只包含兩個(gè)步驟:剪斷項(xiàng)鏈和收集同顏色的珠子。例如下面的一條項(xiàng)鏈(a)從N=3處斷開(kāi)變?yōu)轫?xiàng)鏈(b)。這個(gè)操作只需要將前N個(gè)珠子移到后邊即可。
            brb | rrwb ------> rrwbbrb
               (a)               (b)
        現(xiàn)在只剩下收集同顏色的珠子這一步,根據(jù)上面的例子我們很容易寫(xiě)出下面的程序。
        用變量c來(lái)記錄最左邊珠子的顏色;
        Left:=0;
        FOR i:=1 TO 項(xiàng)鏈長(zhǎng)度 DO
        IF 左數(shù)第i個(gè)珠子的顏色與c相同
        THEN Inc(Left)
        ELSE Break;
        這樣變量Left中存放的就是從左邊收集到的珠子的數(shù)目,同理可求得從右邊收集到的珠子的數(shù)目Right,則所求的值為L(zhǎng)ett+Right。這個(gè)程序顯然能通過(guò)上面的例子,由于這是一道簡(jiǎn)單的題目,誰(shuí)也不想在它上面多費(fèi)時(shí)間,往往做到此為止。可是如果仔細(xì)想想,再舉幾個(gè)例子,就會(huì)發(fā)現(xiàn)錯(cuò)誤。上面的那條項(xiàng)鏈斷開(kāi)后左有兩個(gè)珠子為紅色和藍(lán)色,在題目中這兩種顏色的珠子都比較"普通",只有白色的珠子比較"特殊"。所以應(yīng)舉一個(gè)斷開(kāi)后左右兩端有白色珠子的例子。還是上面那條項(xiàng)鏈入N=6處斷開(kāi)。
        brbrrw| b------->bbrbrrw
        正確答案應(yīng)是收集到5個(gè)珠子:左邊2個(gè),有邊3個(gè)。而上面的程序得到的結(jié)果卻是3個(gè):左邊2個(gè),右邊1個(gè)。錯(cuò)誤就在于沒(méi)有考慮到左右兩端有白色珠子的情況。一種較容易的解決方案是先將左有兩端的白色珠子均取下,記其數(shù)目為Other,再用上面的程序來(lái)求,結(jié)果為L(zhǎng)eft十Right十Other。我們解決了左右兩端出現(xiàn)白色珠子的情況,還有沒(méi)有別的特殊情況呢?一個(gè)真正"特殊"的項(xiàng)鏈不應(yīng)包含所有顏色的珠子,最好只包含一種顏色。如下面的項(xiàng)鏈?zhǔn)怯蒷0個(gè)紅色的珠子組成。
        rrrrrrrrrr
        用我們的程序得出的結(jié)果是20個(gè),顯然是不對(duì)的。因?yàn)轭}目中要求是收集珠子而不是數(shù)珠子,所以最后得到的總數(shù)不應(yīng)超過(guò)珠子的總數(shù)。這雖然只是一個(gè)字眼的問(wèn)題,卻使當(dāng)年中國(guó)隊(duì)的選手失了不少分。一個(gè)簡(jiǎn)單的改正措施是判斷最后的結(jié)果是否大于珠子總數(shù),如果是則輸出珠子的總數(shù)即可。
        雖然項(xiàng)鏈這道題比較簡(jiǎn)單,卻很難"簡(jiǎn)單"地得到滿(mǎn)分,最容易出的錯(cuò)誤就是考慮的不全面。
        2.多項(xiàng)式加法
        由文件輸入兩個(gè)多項(xiàng)式的各項(xiàng)系數(shù)和指數(shù),編程求出它們的和,并以手寫(xiě)的習(xí)慣輸出此多項(xiàng)式。
        要求:
        (1)多項(xiàng)式的每一項(xiàng)axb用axb的格式輸出。
        (2)兩個(gè)多項(xiàng)式在文件中各占一行,每行有2m個(gè)數(shù),依次為第一項(xiàng)的系數(shù),第一項(xiàng)的指數(shù),第二項(xiàng)的系數(shù),第二項(xiàng)的指數(shù)……
        例如輸入文件為:
        l 2 3 0
        -l 1
        輸出:
        x2-x+3
        此題是一道大學(xué)生競(jìng)賽的題目,很多人只用了很短的時(shí)間就編出程序。但最后測(cè)試的結(jié)果卻令他們很驚訝:通過(guò)的數(shù)據(jù)還不到一半!他們犯的錯(cuò)誤歸根結(jié)底就是考慮得不夠全面。
        此題對(duì)于多項(xiàng)式相加的過(guò)程很簡(jiǎn)單,只要找出冪次相同的項(xiàng)相加即可。關(guān)鍵在于題目中要求用符合手寫(xiě)的習(xí)慣輸出結(jié)果。何為手寫(xiě)的習(xí)慣呢?例如多項(xiàng)式3x2-x中就有很多手寫(xiě)的習(xí)慣。我們不會(huì)將其寫(xiě)成3x2一lx1+O。因?yàn)槭紫犬?dāng)某項(xiàng)系數(shù)為1時(shí),我們習(xí)慣于不寫(xiě)系數(shù);其次對(duì)于一次項(xiàng)我們也要省略指數(shù);還有我們從來(lái)不寫(xiě)出系數(shù)為0的項(xiàng)。一個(gè)簡(jiǎn)單的多項(xiàng)式就有這么多的手寫(xiě)習(xí)慣,我們已經(jīng)感覺(jué)到了要把這題全面地做出很不容易。雖然我們平時(shí)總在寫(xiě)多項(xiàng)式,但是誰(shuí)也不會(huì)留心我們寫(xiě)多項(xiàng)式時(shí)的習(xí)慣。我們寫(xiě)多項(xiàng)式的習(xí)慣究竟有哪些呢?
        (1)首先我們考慮對(duì)于多項(xiàng)式中的任一項(xiàng)axb它有多少手寫(xiě)習(xí)慣:
        • 當(dāng)a=0時(shí),此項(xiàng)省去不寫(xiě);
        • 當(dāng)a=l時(shí),省去a;
        • 當(dāng)a=-1時(shí),系數(shù)只寫(xiě)一個(gè)負(fù)號(hào)'-';
        • 當(dāng)b=0時(shí),省去x和b;
        • 當(dāng)b=l時(shí),省去b;
        • 當(dāng)a<一1時(shí),省去此項(xiàng)前面的加號(hào)(首項(xiàng)除外)。
        我們一口氣寫(xiě)了這么多條規(guī)則,每一條看起來(lái)都很正確,但合在一起是否還正確呢?當(dāng)a=l或-1時(shí)要省去其中的數(shù)字1,這是針對(duì)一般情況而言。如果b=0,則數(shù)字1就不應(yīng)當(dāng)省去。所以我們不僅要單獨(dú)考慮a和b,而且要將其和起來(lái)考慮。
        (2)其次對(duì)于整個(gè)多項(xiàng)式有哪些規(guī)則呢?
        • 多項(xiàng)式的首項(xiàng)系數(shù)前不應(yīng)有加號(hào)'+';
        • 如果一個(gè)多項(xiàng)式為零多項(xiàng)式,則應(yīng)寫(xiě)出數(shù)字'0'。
        現(xiàn)在看起來(lái)這道題并不是一道很容易的題目。它需要一個(gè)人在很短的時(shí)間內(nèi)能全面地總結(jié)出上述那么多規(guī)則。這對(duì)一個(gè)人的全面考慮問(wèn)題的能力是一個(gè)很好的檢驗(yàn)。
        3.求最長(zhǎng)的公共子串(NOI'93第一題)
        求N個(gè)字符串的最長(zhǎng)公共子串,N<20,字符串長(zhǎng)度不超過(guò)255。例如N=3,由鍵盤(pán) 依次輸入3個(gè)字符串為
        What is local bus ?
        Name some local buses.
        local bus is a high speed I/O bus close to the processor.
        則最長(zhǎng)公共子串為"local bus"。
        此題也是作為第一題出現(xiàn),同樣有很多入在此題上失分。我們都做過(guò)求n個(gè)數(shù)最大公 約數(shù)的問(wèn)題,在那道題中求3個(gè)數(shù)的最大公約數(shù)時(shí),可以先求兩個(gè)數(shù)的最大公約數(shù),再將此數(shù)與第三個(gè)數(shù)求一次最大公約數(shù)。有人從那道題中得到"啟發(fā)",設(shè)s(p,q)為字符串p 和q的最長(zhǎng)公共子串,則p、q、r的最長(zhǎng)公共子串為s(s(p,q),r)。這樣只需編寫(xiě)一個(gè)求兩個(gè)字符串的最長(zhǎng)公共子串的過(guò)程即可。但這種方法對(duì)不對(duì)呢?看看下面的例子。
        三個(gè)字符串分別為'abc'、'cab'、'c',則s(p,q)='ab',s(s(p,q).r)=''。事實(shí)上這三個(gè)字符串有公共子串'c'。顯然上面的算法是錯(cuò)誤的,原因在于沒(méi)有考慮到本題與求最大公約數(shù)那道題在性質(zhì)上的不同之處。最大公約數(shù)可以由局部解得到全局解,而本題卻不能。正確的做法是列舉出其中一個(gè)字符串的所有子串,找出其中最長(zhǎng)的而且是公共的子串。
        FOR i:=l TO 第一個(gè)字符串的長(zhǎng)度 DO
        FOR j:=i TO 第一個(gè)字符串的長(zhǎng)度 DO
        IF (第i個(gè)字符到第j個(gè)字符的子串為公共子串)AND(j-i+1>當(dāng)前找到的最長(zhǎng)公共子串的長(zhǎng)度max)
        THEN
        BEGIN
        max:=j-i+l;
        最長(zhǎng)公共子串:=此子串;
        END;
        為了提高效率,我們可以將最短的字符串作為第一個(gè)字符串。此題需要考慮的并不像多項(xiàng)式加法那道題那么多,但是它提醒我們?cè)诓磺宄}目的性質(zhì)之前,不能濫用以前的方法。
        4.可重復(fù)排列(NOI'94第一題)
        鍵盤(pán)輸入一個(gè)僅由小寫(xiě)字母組成的字符串,輸出以該串中任取M個(gè)字母的所有排列及排列總數(shù)(輸入數(shù)據(jù)均不需判錯(cuò))。
        此題是由全排列問(wèn)題轉(zhuǎn)變而來(lái),不同之處在于:一個(gè)字符串中可能有相同的字符,導(dǎo)致可能出現(xiàn)重復(fù)的排列。例如從字符串'aab'中取2個(gè)字符的排列只有三種:'aa'、'ab'、'ba'。如何去掉那些可能重復(fù)的排列呢?一種想法就是每產(chǎn)生一種不同的排列就記錄下來(lái),以便讓以后產(chǎn)生的排列進(jìn)行比較判重。這種想法顯然沒(méi)有考慮到隨著字符串長(zhǎng)度的增加,排列將會(huì)多得無(wú)法記錄,而且這種判重方法在效率上也會(huì)很低。最好有一種方法能在產(chǎn)生排列的過(guò)程中就能將重復(fù)的去掉。先看一看全排列的遞歸過(guò)程
        PROCEDURE Work(k);
        BEGIN
         IF k=m+l THEN 打印結(jié)果
                  ELSE FOR i:=1 TO 字符串長(zhǎng)度n DO
                     IF (i<>e[l],e[2],e[k-1]) THEN
                      BEGIN
                       e[k]:=i;
                       Work(k+l);
                      END;
        END;
        讓我們來(lái)分析產(chǎn)生重復(fù)的原因。考慮從字符串。'aab'中取2個(gè)字符的排列。當(dāng)e[1]從l變到2時(shí),字符串中的字符卻沒(méi)有變,都是'a'。這樣我們只要在改變e[k]時(shí),判斷其對(duì)應(yīng)的字符是否也改變。即在上面的過(guò)程的循環(huán)中加一句判斷(設(shè)字符串為s):IF s[i]<> s[e[k]] THEN …; 這當(dāng)然只是一個(gè)粗略的想法,我們僅僅用上面的例子就能發(fā)現(xiàn)問(wèn)題: 程序在對(duì)e[k]的每一次賦值之前都要進(jìn)行一次判斷,而不是我們預(yù)想的在改變e[k]時(shí)才進(jìn)行判重。我們用一個(gè)布爾型的局部變量First來(lái)記錄是否是對(duì)e[k]進(jìn)行第一次賦值。修改后的程序如下:
        PROCEDURE Work(k);
        BEGIN
        First:=True;
        IF k=m+l THEN 打印結(jié)果
         
        ELSE FOR i:=1 TO 字符串長(zhǎng)度n DO
        IF (i<>e[l],e[2],e[k-1]) THEN
        BEGIN
        First:=false;
        e[k]:=i;
        Work(k+l);
        END;
        END;
        很多選手的程序到此就為止了,可是它還有一個(gè)致命的錯(cuò)誤:我們?cè)谂兄貢r(shí)假定這個(gè)字符串中的字符已經(jīng)排好順序,即相同的字符已經(jīng)連在一起。事實(shí)上并不是這樣,輸入的字符串中的字符排列是任意的,需要我們?cè)谶f歸之前作一次排序的初始化才能保證程序運(yùn)行得正確。可見(jiàn)雖然本題的難點(diǎn)是在遞歸過(guò)程中,但是那些簡(jiǎn)單的初始化卻是程序最容易忽略,最容易出錯(cuò)的部分。
        刪除多余括號(hào)(IOI'94國(guó)家隊(duì)選拔賽第一題)
        鍵盤(pán)輸入一個(gè)含有括號(hào)的四則運(yùn)算表達(dá)式,可能含有多余的括號(hào),編程整理該表達(dá)式,去掉所有多余的括號(hào),原表達(dá)式中所有變量和運(yùn)算符相對(duì)位置保持不變,并保持與原表達(dá)式等價(jià)。
        例:輸入表達(dá)式
        a+(b+c)
        (a*b)+c/d
        a+b/(c-d)
        應(yīng)輸出表達(dá)式
        a+b+c
        a*b+c/d
        a+b/(c一d)
        注意輸入a+b時(shí)不能輸出b+a。
        表達(dá)式以字符串輸入,長(zhǎng)度不超過(guò)255。輸入不要判錯(cuò)。
        所有變量為單個(gè)小寫(xiě)字母。只是要求去掉所有多余括號(hào),不要求對(duì)表達(dá)式化簡(jiǎn)。
        同多項(xiàng)式加法一樣,此題要求的也是一個(gè)我們平時(shí)很習(xí)慣但卻沒(méi)有注意的規(guī)則:去掉多余的括號(hào)。哪些括號(hào)是多余的呢?這要根據(jù)緊挨著括號(hào)前后的運(yùn)算符號(hào)和括號(hào)中最后一個(gè)運(yùn)算符號(hào)來(lái)決定。例如表達(dá)式a+(b*c+d)-e中,括號(hào)前的符號(hào)為"+",括號(hào)后的符號(hào)為"-",括號(hào)中最后一個(gè)運(yùn)算符號(hào)為"+",所以括號(hào)是多余的。總結(jié)括號(hào)中最后一個(gè)運(yùn)算符號(hào)為"+"、"-"、"*","/"時(shí),括號(hào)前、后為何運(yùn)算符號(hào)時(shí)括號(hào)是多余的,我們很容易得出表1.1。
        表1.1 多余的括號(hào)滿(mǎn)足的條件

        括號(hào)前的符號(hào)
        括號(hào)中的符號(hào)
        括號(hào)后的符號(hào)
        +
        +
        +、-
        +
        -
        +、-
        +、-、*
        *
        +、-、*、/
        +、-、*
        /
        +、-、*、/

         
        上表只是對(duì)一般情況的分析,顯然是很不全面的。首先括號(hào)前,括號(hào)中和括號(hào)后都可能無(wú)運(yùn)算符號(hào),例如表達(dá)式((a))+b;其次變量前還可能帶有負(fù)號(hào),例如表達(dá)式(-a)+ (-b)中的括號(hào)一個(gè)是多余的,一個(gè)不是多余的。還有一些其它的情況如表達(dá)式只有括號(hào)無(wú)任何變量等需要考慮。此題留給大家自己去完成。注意多用一些特殊的數(shù)據(jù)來(lái)測(cè)試自己的程序。大家也可以試著用表達(dá)式樹(shù)的方法來(lái)做此題。
        6.合并表格(NOI'93第二題)
        在兩個(gè)文本文件中各存有一個(gè)西文制表符制成的未填入任何表項(xiàng)的表結(jié)構(gòu),分別稱(chēng)之為表1和表2,要求編程將表1和表2按下述規(guī)則合并成表3。
        規(guī)則:表1在上表2在下,表1與表2在左邊框?qū)R,將表1的最底行與表2的最頂行合并。
        例如,3張表見(jiàn)圖1.2。
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
        表1
        表2
        表3
        圖1.2
        編程要求:
        (l)程序應(yīng)能從給定的文本文件中讀入兩個(gè)源表并顯示。
        (2)若源表有錯(cuò),應(yīng)能指出其錯(cuò)(錯(cuò)誤只出在表1的最底行和表2的第一行)。
        (3)將表1和表2按規(guī)則合并成表3,并顯示之。
        (4)所有制表符的ASCII碼應(yīng)由選手自己從給出的示例文件中截取。
        我們把此題的分析留給讀者去獨(dú)立完成。
        "千里之堤,毀于蟻穴"。一些程序往往不是錯(cuò)在算法上,而是錯(cuò)在考慮得不全面上。希望通過(guò)以上幾個(gè)例子,能使大家對(duì)此引起重視,在以后的編程中多加注意,避免不應(yīng)有的遺憾。
         
         

        [標(biāo)簽:競(jìng)賽聯(lián)賽 學(xué)習(xí)方法]

        分享:

        高考院校庫(kù)(挑大學(xué)·選專(zhuān)業(yè),一步到位!)

        高考院校庫(kù)(挑大學(xué)·選專(zhuān)業(yè),一步到位!)

        高校分?jǐn)?shù)線

        專(zhuān)業(yè)分?jǐn)?shù)線

        日期查詢(xún)
        • 歡迎掃描二維碼
          關(guān)注高考網(wǎng)微信
          ID:gaokao_com

        • 👇掃描免費(fèi)領(lǐng)
          近十年高考真題匯總
          備考、選科和專(zhuān)業(yè)解讀
          關(guān)注高考網(wǎng)官方服務(wù)號(hào)


        主站蜘蛛池模板: 日本免费一区二区在线观看| 男女疯狂一边摸一边做羞羞视频| 成人爽a毛片在线视频| 亚洲欧美丝袜制服在线| 美女被视频在线看九色| 国产欧美综合一区二区三区| eeuss影院在线观看| 日本免费观看网站| 亚洲日韩乱码中文无码蜜桃| 精品亚洲福利一区二区| 国产破外女出血视频| 亚洲黄色小说网| a级片免费在线播放| 日韩国产成人精品视频| 国产国产精品人在线视| 一级做a爰片久久毛片免费看| 欧美日韩视频在线成人| 午夜视频一区二区三区| 国产1000部成人免费视频| 夜夜爽夜夜叫夜夜高潮漏水| 中文字幕无码乱码人妻系列蜜桃 | 少妇被又大又粗又爽毛片久久黑人 | 日韩精品无码一区二区三区不卡 | 欧美亚洲国产一区二区三区| 免费成人福利视频| 芬兰bbw搡bbbb搡bbbb| 国产精品91av| 92国产福利久久青青草原| 无码人妻丰满熟妇区免费| 五福影院最新地址| 欧美高清一区二区三区| 四虎国产成人永久精品免费| 一个色综合导航| 手机看片你懂的| 亚洲国产精品嫩草影院久久 | 国产18禁黄网站免费观看| 黑人巨大sv张丽在线播放| 成人字幕网视频在线观看| 九九久久精品国产免费看小说 | 外卖员被男顾客gay| 久久久久久久99精品免费 |