天天看點

Noip2013錯誤避免

    很多的時候,我們會說,這道題我會做,算法想出來了,但是這裡那裡少了一些判斷,導緻一分未得,或是說變量名錯誤,或者說幹脆是檔案名錯誤。這些都不是理由,如果火箭發射半空爆炸,可以說是控制器中一個運算符錯誤就可以逃避所有責任嗎?不可以,同樣,OI也不行,是以隻有提升自己,使自己成為一個嚴謹的人!

基本操作

  1.讀題一定要仔細,特别是長題目,千萬不要主觀臆斷,一定要完全了解題目再去程式設計。A good reader is what he reads! 讀題時要注意用樣例模拟一下自己所了解的題目意思,若正确才開始程式設計。

  2.檔案讀入與輸出檢查很重要,最好指定路徑在自己電腦上試一下,不過不要忘記将路徑改回來。如果比賽時電腦沒問題時,直接在原檔案夾下進行。

  3.特别注意數組範圍一定要開的大一些,而且下界最好定為-1。特别是一些會調用0和-1 的題目。

  4.看清題目輸出,比如‘good!’,千萬不要少打一個‘!’導緻全盤皆輸。

  5.變量一定不要打錯,上次在打小根堆時最後交換變量打錯,将t指派為父親,父親指派為兒子之後,又把兒子指派成了父親,結果本來AC的程式變成了全錯。

初始化

  1.給數組賦初值時,如果一會要相加判斷的,一定記住賦保險一點的 ($7f div 3),如果有相乘判斷的也必須注意相乘超上限的問題(215錯誤)。

      2.在計算時初始化很重要,特别記住LIS數組和答案的初始化都為1。因為本身就是一個lis。

  3.關于fillchar與filldword:

  fillchar是指派極大值,0和-1時用的,int64與longint均可:

  fillchar(a,sizeof(a),$7f):指派為極大值;

  fillchar(a,sizeof(a),0):指派為0;

  fillchar(a,sizeof(a),$FF):指派為-1;

  filldword是指派任意值用的,但是隻限longint:

  filldword(a,sizeof(a)>>2,x):指派為x;

  注意右移2位,因為是按位指派的是以一定要右移。

  還有如果是小範圍指派,不是整個數組的話,用for循環更快!

       4. 并查集在運算前一定要預處理 f[i]=I,  否則後果很嚴重。

範圍選擇

      1. 一定要看清資料範圍,并且計算出中間變量的隐藏範圍,才決定用int64或是longint,在能使用longint的情況下不要使用int64,因為會降低速度。

  2.堆式線段樹範圍一定要開至六倍左右,最為保險,位運算壓縮記憶體如果記不清就不要用了。

  3.前向星數組要開到邊數的兩倍以上,否則會記憶體溢出。

算法錯誤

  1.切記,字首和一定要在排序後計算,否則會導緻出錯。

  2.最短路弗洛伊德算法循環一定不可以換!Dijkstra算法不能求有負權的最短路!

  3.特别記住,pos函數字串寫在母串前,傳回值為字串在母串中位置。

  4.在打二分答案的代碼時,一定要注意,厘清楚答案是單調遞增或是單調遞減,調試不出時可以考慮一下這個緻命錯誤,比如我在做聰明的質檢員時,沒分析清楚答案單調性的走向,導緻錯誤,太可怕了。

  5.在打連結清單插入時,一定要注意是x<a[i].brother 且((x<I)or(a[i].brother=0)))時插入。(特别注意,是x<a[i].brother 而不是x<i),調試時特别注意~

  6. 記住,在利用循環變量求一個值時一定要用範圍擴大法,而且切記不能打成k:=int64(i*i)而是k:=int64(i)*int64(i)。

  7. 樹狀數組和線段樹邊界條件一定要看清楚,等于有還是沒有一定認真思考,多次被坑的經驗。

  8.并查集中并入的操作為f[f[i]]=f[j],不要少打f。

  9.如果在過程中要改變過程裡的變量,則要用var比如擴歐。

程式優化

  1.同一個資料不要反複計算,可以儲存以提高程式效率,比如打聰明的質檢員時,我本來打的是check與s比較,将check與s做差,與tmp比較,反複調用了兩次過程,就在nlogn的算法中加入了2的常數,後果可想而知,時間擴大了兩倍啊!

  2.在判斷兩個條件用and連接配接時,應該讓适用範圍狹窄的放在前面,這樣就可以減少判斷次數,因為如果第一個條件不滿足就不會去判斷第二個條件,切記,有些時候,這是一個很強大的優化。

  3.位運算相當重要,比如二分或是簡單的乘除,若可以用上則盡量代替。

  4.集合的搬運用Move函數取代直接複制:

  Move(f[I],g[j],s*sizeof(f[1]));

  表示從f數組第I為開始搬運s長度的資料至g數組第j位開始的地方。

記憶體占用計算

  千萬不要因為超記憶體而0分!

  1 位元組 :Boolean -- 布爾型 ; int Short ( -128~127 ) , Byte ( 0~255 ) -- 最小的整型 ; char --字元型 ;

  2位元組: Integer ( -32768~32767 ) 、 Word ( 0~65535 ) -- 常用的整型 ;

  4位元組:  longint ( -2147483648~2147483647 ) -- 長整型; Single ( 1.5e-45~3.4e38 )-- 單精實型 ;

  6 位元組:  real( 2.9e-39~1.7e38 ) -- 标準實型 ;

  8位元組: Int64 ( -2^63+1~2^63-1 ) -- 整型; Double ( 5.0e-324~1.7e328 ) -- 雙精度實型; Qword ( 0~2^64-1 ) -- 整型; Comp ( -2^63+1~2^63-1 ) -- 裝配十進制實型 ;

  10位元組:Extended ( 1.9e-4951~1.1e4932 ) -- 擴充實型 ;

特殊:String (長度最大為 255 的字元串 ) ; Ansistring (超長字元串 , 長度不限) .

算空間的公式:總空間 =( 總位元組數 /1024/1024)MB

比賽限制:  NOIP:256MB;  ZJOI:512MB

題目細節

  有時候考完模拟賽,總會有這樣的抱怨聲:希哥的資料怎麼這麼坑啊,怎麼想的到。NOIP肯定也是會有這樣的資料的,許多的時候,不是我們想不到,而是沒有去想,隻是過了樣例就欣喜若狂,或是僅僅是樣例一類的小資料。在做題完後,一定要從一個出題者的難度劃分角度思考,那些地方可以坑人,就比如smartoj裡數星星這一題,沒說給出的坐标X2>X1且Y2>Y1,是以就要分類讨論,還有就是0的考慮,高精度負數特殊處理的考慮,組合數1和0的考慮,遞歸邊界的考慮,不要給資料一點可趁之機。

資料制造

     如何在一個過了樣例的程式裡檢查呢,隻有自己制造測試資料,測試資料分為幾種:

  1. 小資料,可以手動驗證準确性的資料。
  2. 中等資料,對拍時使用(不過要保證暴力程式的正确性)
  3. 邊界資料,選取一些容易出現問題的資料,看看程式是否會崩潰。
  4. 極限資料,寫一個程式maker制作資料,看是否發生棧溢出或是其他一些錯誤。用時間函數記錄時間觀察是否逾時。

  時間函數:

  Uses sysutils; time:real;

  Begin

    Time:=now;

    …… { 主程式部分 }

    Writeln((now-time)*86400:0:3);// 時間變量的機關是 “ 天 ” , 是以要轉化為 “ 秒 ”

  End.

  P處理樣本:

  :loop

    maker.exe>cut.in

    cut.exe<cut.in>cut.out

    cut1.exe<cut.in>cut1.out

    fc cut.out cut1.out

    if errorlevel 1 goto end

  pause

  goto loop

  :end