2021 - 1! Review

Arvin Liu @ Sprout 2021

Voting

蛤?

Voting

我還是不會講迷宮 ☆(ゝω・)v

Schedule

  • 變數 / 運算子 / 轉型
  • If-else
  • 迴圈 - while / do-while / for-loop
  • 陣列 - Array
  • 解題 -  696 矩陣卷積 I
  • 字元陣列 - C-string
  • 解題 -  6003 小普的人情節
  • 函式編寫 - Function
  • struct編寫
  • 解題 -  696 矩陣卷積 ===============================
  • 解題流程 - Solving Problem

變數 & 運算

變數 & 型態

  • 宣告一個int (整數)型態的變數x。

 

  • 每個字母都有對應的數字代表(Ascii code)。
    • ​單引號可以使用這個數字。

 

  • 浮點數 (有小數點的數字) 用 double 型態。
     
  • 當整數會超出2147483647 ( = 2^31 -1 ),不能用int,
    改用long long。
  • 如果這個數字非常多位數(例如十萬位),表示不能用數字存起來,要用陣列去做。
int x;
char c='a'; // c 等於數字 97

各種運算符號 & 順序

  1.  括號 () 裡面會被優先處理。
  2.  struct的"的"的那個. / 反轉! 
  3.  ++系列: 變數自己加1。
  4.  乘*/還有取餘數%
  5.  加+-
  6.  判斷一不一樣 ==!=
  7.  判斷大小 <<=>>=
  8.  兩個條件式的"" &&
  9.  兩個條件式的"" ||
  10.  三元運算子 <條件> ? <如果是> : <如果不是>
  11.  等於系列(修改左邊的變數)  =+=*= ...。

不會背順序,()就對了。

if ( a && b || c && d)
if ( (a && b) || (c && d))

這兩個等價。

不會i++和++i的性質就不要亂用。直接寫x += 1。

if 裡面的等於記得是兩個

順序不用背啦...

常見錯誤

  • 很多時候,你可能需要應付整數和浮點數的轉換。
    • 例如算出全班平均成績,此時你可能會這樣寫。

 

 

  • 你會發現結果不會是54.87,而是54。因為整數除法會先運算導致精度已經喪失,才用 = 給average。
  • 此時的解決辦法:
    • 強制轉型 - 在前面寫 (你要轉的型態)
       
    • 隱式轉型 - 在前面寫用魔法讓程式在除之前變浮點數。 

 

int total_score = 5487;
int student_num = 100;
double average_score = total_score / student_num;
average_score = (double) total_score / student_num;
average_score = 1.0 * total_score / student_num;

if-else

基本用法

  • 如果<A>,做<B>。小括號表條件,大括號表做事。

 

 

 

  • 如果<A>,做<B>,否則做<C>

 

 

 

 

  • 如果不寫大括號,那麼隱藏大括號的效力會只有一行。
    • 如果下一行是一段code,例如另一個if或for,效力會變成那段code。
if (A) {
  // do B
}
if (A) {
  // do B
} else {
  // do C
}

一個分號表示一行

if (A)
  if (B)
    C();
  else
    D();

如果A{如果B做C否則做D}

常見特別用法

  • 如果變數x等於1,做<A>,等於2做<B>,等於3做<C>

 

 

 

  • 如果一個很長的判斷式不成立的時候,做A。
    • 例如 : x == 1 && y ==2 || z == 3 && i == -1
if (x == 1) {
  // do A
} else if (x == 2) {
  // do B
} else if (x == 3) {
  // do C
}
if (x == 1 && y ==2 || z == 3 && i == -1) {
} else{
  // do A
}
if (!(x == 1 && y ==2 || z == 3 && i == -1)) {
  // do A
}

邏輯上對,但不要這樣寫,很冗

用驚嘆號反轉結果 !

常見錯誤

  • 不加大括號的if不需要分號。

 

 

  • 判斷 x 是不是在 0 ~ 10之間。
    • 不能直接混寫條件式。



       
    • 用&&拆開來寫。
if (x == 1);
  A();
// 不管怎麼樣都跑的到A,if沒有作用。
if (0 <= x <= 10) {
  // do A
}
// 會變成 ((0 <= x) <= 10),
// (0 <= x) 只會是 0(False)或1(True),這都<=10。
// 所以這個if相當於一定會是True。
if (0 <= x && x <= 10) {
  // do A
}

迴圈 Loop

三種迴圈用法

  • while迴圈,如果<A>是對的做<B>。做完重檢查一次<A> ...

 

 

  • do-while迴圈,先做<B>,做完如果<A>成立,再做一次 ... 

 

 

 

  • for迴圈,先做<I>,如果<A>是對的做<B>。做完<B>後做<C>,之後重新檢查一次<A>,對的就繼續做<B> ...
while (A) {
  // do B
}
do {
  // do B
} while (A);
for ( I ; A ; C ) {
  // do B
}
  1. 記得結尾加分號
  2. 比較不常用,可以不記。
  3. 用在需要先做事情的時候。
  1. 記得中間用分號隔開。
  2. 常用在固定次數的循環。
  1. 常用在不固定次數的循環。

常見的例子 - 1

  • 3n + 1 問題
    • 對於一個偶數,除以2。
    • 對於一個奇數,乘3加1。
    • 輸出所有過程,直到1。

 

  • 不固定次數
    • 用while迴圈比較好
  • 參考用code:
while (x != 1) {
  if (x % 2 == 0)
    x /= 2;
  else
    x = x*3+1;
}

常見的例子 - 2

  • 亂數產生問題
    • 產生一個亂數,他具有某種性質。(結合for迴圈可以做到產生不重複的亂數)
  • 不固定次數,且至少做一次。
    • 用do-while迴圈比較好

 

  • 參考用code: 產生出不被7整除的數字。
do {
  x = rand();
} while (x % 7 == 0);

控制流程 : break / continue

Loop

起始點

break;

Loop

起始點

直接出迴圈

Loop

起始點

Loop

起始點

放掉這次迴圈,
從起點再來

continue;

常用時機

遇到特殊狀況就放棄迴圈。

  • 使用者輸入exit的時候。
  • 程式出錯,強制終止。
  • 已經算出答案,不用再回圈的時候。

遇到特殊狀況就忽略迴圈的事情。

  • 使用者指令打錯,請他重新輸入東西的時候。
  • 本來for裡面if-else架構,
    寫成if + continue。

陣列 Array

宣告以及使用 - 當時的 10sec

  • 開一個空間為10 * 20的二維陣列,預設全0。

 

  • 開一個空間為10 * 20 * 30 的三維陣列,預設全0。

 

  • 用一個三維陣列的值,如讓第0個二維陣列裡的第2個一維陣列裡面的第5個值等於10

 

  • 總之二維陣列就是一維陣列的一維陣列,三維陣列就是一維陣列的二維陣列(?)
int ary[10][20]={0};
int ary[10][20][30]={0};
ary[0][2][5] = 10;

最常見的用法 - 1

  • 輸入n個數字的序列並且儲存。
     
  • 通常固定次數。
    • 用for迴圈比較好
       
  • 參考用code:
    輸入n個數字到陣列ary裡面。
cin >> n;
for(int i=0 ;i<n; i++){
  cin >> ary[i];
}

最常見的用法 - 2

  • 輸入w*h*r個三維數據並且儲存。
     
  • 通常固定次數。
    • 三層for迴圈
       
  • 參考用code:
cin >> n;
for(int i=0 ;i<w; i++)
 for(int j=0 ;j<h; j++)
  for(int k=0 ;k<r; k++)
   cin >> ary[i][j][k];

常見錯誤

  • 判斷兩個陣列一不一樣不能直接等於。

     

  • 除了初始化,不能用{}給值。 (只能一個一個給。)

     
  • 用變數當作空間大小。(一次就開最大的可能。)

 

 

  • 開空間很大的陣列要去全域變數宣告。(不然會吃RE。)
if (A == B){
  // do something
}
A = {1, 2, 3};
int n;
cin >> n;
int ary[n];

停一下 (?)

稍微看一下剛剛的投影片吧!

手把手 - 矩陣卷積

沒有函式的版本。

字串 C-string

字元 & 字串(字元陣列)的本質

  • 你知道這幾個的區別嗎? "0", '0', '\0', 0
    • "0"""表示字串,所以它是長度為1,內容為0的字串。
    • '0': ''表示字元字元0根據ASCII數字48
    • '\0': 特殊跳脫字元,表示字串結尾符號
    • 0: 數字(int) 0。拿來做數字運算的。
  • 字元宣告直接使用 char 就可以了。數值範圍是-128~127。


     
  • 在C裡面,字串就是字元的陣列。所以以下兩段等價。
char c = 'a';
// c 根據ASCII碼,為數字97。
char S[7] = {'K', 'o', 'r', 'o', 'n', 'e', '\0'};
char S[7] = "Korone";

字串常用的函式

  • strlen (string length) : 求這個字串S的長度。

 

  • strcpy (string copy) : 複製字串A到字串B的空間裡面。

 

  • strcat (string concatenate) : 把A字串附加在B後面。

 

  • strcmp (string compare) : 判斷字串A和B的大小,如果一樣結果會是0

 

 

 

int len = strlen(S);
strcpy(B, A);
strcat(B, A);
if(strcmp(A, B) == 0){
  // A, B the same.
}

老實說我根本沒用過strcpy 和 strcat ... 有更多用途更廣的函式可以替代。

#include <cstring>
#include <string.h>

常見錯誤 - 1

  • 對一個字串S,遍歷所有字元。
    • 阿不就for + strlen ?


       
    • 事實上這樣會TLE(超時)。因為上面其實是雙重迴圈...

 

 

  • 記得空間要多開1。
    • 因為有字串結尾符號 '\0'
for(int i=0; i<strlen(S); i++){
  // do something
}
int len = strlen(S);
for(int i=0; i<len; i++){
  // do something
}
// name長度為1~10
char name[10 + 1]; // 記得加1多留給'\0'
cin >> name;

常見錯誤 - 2

  • 判斷兩個字串的相等。
    • 跟陣列一樣不可以直接用等於。


       
    • 要用for迴圈判斷,或者直接使用strcmp

       

  •  
if (A == B){
  // do something
}
int lenA = strlen(A);
bool is_same = lenA == strlen(B);
for(int i=0; i<lenA; i++)
  if(A[i] != B[i])
    is_same = false;
if(is_same){
  // do something
}
if (strcmp(A, B)==0){
  // do something
}

手把手 - 小普的情人節

(Optional) 字串私心推薦技巧

  • 強制截斷字串S,讓字串長度最多為n。

 

 

  • 輸入在字串S的第n個之後。 (前n個是本來的,後面是輸入的)

 

 

  • 強制讓某個字串空間S都變成 c。(常用在初始化,二維也ok)

 

S[n] = '\0';
std::cin >> (S + n);
memset(S, c, sizeof(S));

函式 Function

啥時要用到函式?

  • 減少重複編寫同樣的程式碼。
    • 這也會讓你debug修改的次數少一點。
  • 編寫程式時邏輯更流暢。
    • 如果重複的code太常出現會拖長讀code的時間。
  • 增加程式的可讀性。
    • 這樣Debug也會更加容易:)。

reference: 軒爺的投影片

如何寫一個函式?

f(x, y)= (x + y) ^2 - x-y
  • 數學式程式的轉換
int f(int x, int y){
   return (x+y) * (x+y) - x - y;
}

函數名稱

f

參數

x, y

等於甚麼?

用小括號包起來,
記得給型態

要給等於甚麼的型態

  • 數學式程式的轉換

不是個數學式? - void

  • 印出喵的函式
void meow(){
  cout << " ^   ^      " << endl;
  cout << "(=-w-=)----?" << endl;
  cout << "  \" \"   \" \" " << endl;
}

常見錯誤 - 1

  • 不是void的函式但沒有return值。



     
  • 不能一次回傳一個陣列。(怎麼傳多個東西2!會講。)



     
  • return之後函式就結束了。所以return後的code都碰不到。
bool is_out(int x, int y){
  if(x < 0 || y < 0 || x >= n || y >= m)
  	return 0;
    
}
int[5] hello(){
  int a[5] = {0};
  return a;
}
bool is_out(int x, int y){
  if(x < 0 || y < 0 || x >= n || y >= m)
  	return 0;
  return 1;
}
int f1(){
  return 1;
  cout << "Watame wa warukunaiyone~";
}

常見錯誤 - 2

  • 正常情況,函式的參數是pass by value,在函數操作變數不會改到原本的值。(你只會改到函式複製的。)
    • 舉例: 交換兩個變數
void swap(int x, int y){
  int tmp = x;
  x = y;
  y = tmp;
}

參數不是陣列,也沒有&, *之類的東西

int x = 2, y = 3;
swap(x, y);
cout << x << y;
// should be 32
void swap(int &x, int &y){
  int tmp = x;
  x = y;
  y = tmp;
}

使用的
時候

只會改到函式複製的值,也就是
pass by value (只傳數值),
不會改到呼叫函式時的x, y

變數前面加 & 表示
pass by reference (傳本來的變數),這樣就可以改到原本的值

手把手 - 矩陣卷積

轉成函式的版本。

struct

我不知道struct的中文該怎麼翻...

你可以直接點過去,
如果你想知道更多關於struct的語法。

啥時要寫struct?

  • 方便管理變數。
    • 你會很清楚的知道那些變數是屬於那些類別。
      假設一個怪獸有血量,位置,屬性,你可以直接用monster.hp / monster.position 比較不會搞混。
  • 使用constructor建構子可以快速初始化。
  • 增加程式的可讀性。
    • 這樣Debug也會更加容易:)。

如何寫一個struct?

  • 定義型態 - 座標struct
    • struct的成員
      •  
      •  
    • struct的建構子
      • 沒參數
        • 都初始化為0。
      • 兩個參數
        • 直接放進去。
    • 一個函數 f
      •  
struct coord {
  
  int x;
  int y;
  
  coord () {
    x = y = 0;
  }
  
  coord (int _x, int _y) {
    x = _x;
    y = _y;
  }
  
  int f () {
    return x * y ;
  }

};
int x;
int y;
return x*y;

如何用一個struct?

  • 宣告座標c,初始化(0, 0)


     
  • 宣告座標c,初始化(2, 3)

     
  • 印出座標c的x軸資訊

     
  • 印出座標c的
struct coord {
  
  int x;
  int y;
  
  coord () {
    x = y = 0;
  }
  
  coord (int _x, int _y) {
    x = _x;
    y = _y;
  }
  
  int f () {
    return x * y ;
  }

};
coord c;
xy
coord c();
coord c(2, 3);
cout << c.x;
cout << c.f();

常見錯誤 - 1

  • 記得要加分號
  • 建構子不需要type,也不需要回傳值(return)。
  • 函式參數名稱(包括建構子)和成員名稱相撞?
struct coord {
  int x, y;
  coord (int x, int y) {
    x = x, y = y;
  }
};
struct coord {
  int x, y;
  coord (int _x, int _y) {
    x = _x, y = _y;
  }
};
struct coord {
  int x, y;
  coord (int x, int y) {
    this -> x = x;
    this -> y = y;
  }
};

this -> 的用法 2!可能會教(?)

常見錯誤 - 2

  • 預設建構子(參數為空,甚麼事情也不做,也不會初始化的建構子) ,只有在沒有寫建構子才會出來。
struct coord {
  int x, y;
  coord (int _x, int _y){
    x = _x, y = _y;
  }
};
struct crood {
  int x, y;
  coord (){x = y = 0;}
  coord (int _x, int _y) {
    x = _x, y = _y;
  }
};
coord c;

宣告

使用

coord c;
struct coord {
  int x, y;
};
coord c;

error: no matching function for call to ‘coord::coord()’

OK : 符合其中一個自己寫的建構子

OK : 使用預設建構子

遞迴 Recursion - I

這我就不講了 嘿嘿。

最後再停一下 (?)

來收尾吧!

解題(可能的?)流程

解題流程

讀題

寫code

Debug

想算法

讀這個題目在幹嘛?

想解答 - 程式要怎麼寫?

實作你
的想法

WA掉了:(
找錯誤

解題流程

讀題

寫code

Debug

想算法

解題流程

讀題

寫code

Debug

想算法

  • 分析題目再講什麼 (廢話?)
    • 過濾故事 / 幹話。
    • 如果短時間看題目看不懂,結合範例測資來猜題。
    • 注意測資範圍跟配分。
      • 測資太大可能會讓你有些解答變成不可解

解題流程

讀題

寫code

Debug

想算法

  • 過濾故事 / 幹話。
  • 如果短時間看題目看不懂,結合範例測資來猜題。
  • 注意測資範圍跟配分。

    • 測資太大可能會讓你有些解答變成不可解

題目:

給n個數字,數字範圍在
              之間。之後詢問Q次,每次詢問一個數字y,問y存不存在之前的n個數字之內。

0\sim 10^9

一個最簡單很慢解法:

用大小為n的陣列紀錄,每次詢問就用for看y在不在這個陣列裡面。

一個有趣很快,但不可行的解法:

輸入x時讓n[x] = 1,
判斷時用n[y]決定有沒有出現過。

陣列無法開到         這麼大。

10^9

解題流程

讀題

寫code

Debug

想算法

  • 注意測資範圍跟配分。

再難的題目都有基本分可以喇,
不會寫滿分就先喇再說,至少有分數。

解題流程

讀題

寫code

Debug

想算法

解題流程

讀題

寫code

Debug

想算法

  • 看配分做事情。
    • 你想的到可以解決所有測資的算法嗎?​
  • 想到很多種作法 ?
    • 一個簡單的寫法,但是只可以拿到 30% 的分數。
    • 一個困難的寫法,但是可以拿到滿分
      • 只是這個困難的寫法你可能會寫很久或不小心有錯 :(。

解題流程

讀題

寫code

Debug

想算法

  • 一個簡單的寫法,但是只可以拿到 30% 的分數。
  • 一個困難的寫法,但是可以拿到滿分
    • 只是這個困難的寫法你可能會寫很久或不小心有錯 :(。

題目:

給定            ,找出一個整數   ,在               之間

使得                       最大

a, b, c
x
0 \sim 10^{10}
ax^2 + bx + c

簡單的寫法:
for迴圈寫一寫。

比較困難的寫法:

= a(x + \frac{b}{2a})^2 - \frac{b^2-4ac}{4a}

所以答案會是

0 , 10^{10} , \lfloor\frac{-b}{2a} \rfloor, \lceil\frac{-b}{2a} \rceil

之一。

0 \sim 10^{2} ?

那範圍如果是

解題流程

讀題

寫code

Debug

想算法

解題流程

讀題

寫code

Debug

想算法

  • 縮排記得縮好。
    • 不然你可能會大括號
      錯地方😢
  • 不要寫得像右邊那樣。
                                                     /*[*/#include<stdio.h>//
                         #include<stdlib.h>//]++++[->++[->+>++++<<]<][(c)2013]
                        #ifndef                                           e//[o
                       #include<string.h>//]![misaka.c,size=3808,crc=d0ec3b36][
                      #define e                                           0x1//
                     typedef struct{int d,b,o,P;char*q,*p;}f;int p,q,d,b,_=0//|
                  #include __FILE__//]>>>[->+>++<<]<[-<<+>>>++<]>>+MISAKA*IMOUTO
                #undef e//[->[-<<+<+<+>>>>]<<<<<++[->>+>>>+<<<<<]>+>+++>+++[>]]b
             #define e(c)/**/if((_!=__LINE__?(_=__LINE__):0)){c;}//[20002,+[-.+]
            ,O,i=0,Q=sizeof(f);static f*P;static FILE*t;static const char*o[]={//
          "\n\40\"8oCan\40not\40open %s\n\0aaFbfeccdeaEbgecbbcda6bcedd#e(bbed$bbd",
        "a6bgcdbbccd#ead$c%bcdea7bccde*b$eebbdda9bsdbeccdbbecdcbbcceed#eaa&bae$cbe",
       "e&cbdd$eldbdeedbbdede)bdcdea&bbde1bedbbcc&b#ccdee&bdcdea'bbcd)e'bad(bae&bccd",
      "e&bbda1bdcdee$bbce#b$c&bdedcd%ecdca4bhcdeebbcd#e$b#ecdcc$bccda7bbcc#e#d%c*bbda",
     ">bad/bbda"};static int S(){return(o[p][q]);}static/**/int/**/Z=0  ;void/**/z(int//
    l){if(/**/Z-l){Z=l;q++;if(p<b*5&&!S()){p+=b;q=0;}}}int main(int I,    /**/char**l){//
   d=sizeof(f*);if(1<(O=_)){b=((sizeof(o)/sizeof(char*))-1)/4;q=22; p=     0;while(p<b*5){
  /*<*/if(Z-1){d=S()>96;i=S()-(d?96:32) ;q++;if(p<b*5&&!S()){p+=b;  q=      0;}Z=1;}/*[[*/
  while(i){_=o[0][S()-97];I=_-10?b:1;   for( ;I--;)putchar(_ );if   (!      --i||d)z(~i );}
 if(p==b*5&&O){p-=b;O--;}}return 0U;   }if(! (P=( f*)calloc /*]*/  (Q        ,I)))return 1;
 {;}for(_=p=1;p<I;p++){e(q=1);while    (q<   p&&  strcmp(  l[p     ]         ,l[(q)]))++  q;
 t=stdin;if(q<p){(void)memcpy/* "      */    (&P  [p],&P   [q     ]          ,Q);continue ;}
if(strcmp(l[p],"-")){t=fopen(l         [     p]   ,"rb"   )                  ;if(!t ){{;}  ;
printf(05+*o,l[p ]);return+1;                      {;}                       }}_=b= 1<<16   ;
*&O=5;do{if(!(P[p].q=realloc   (P[p].q,(P[p].P     +=       b)+1))){return   01;}O   &=72   /
6/*][*/;P[p].o+=d=fread(P[p]      .q       +P[     p           ].       o,  1,b,t)   ;}//
 while(d==b)      ;P [p].q[       P[       p]                  .o       ]=  012;d    =0;
 e(fclose(t        )  );P         [p]      .p                  =P[      p]  .q;if    (O)
 {for(;d<P[            p]          .o     ;d=                   q+     1)    {q=     d;
  while(q<P[                        p].o&&P[                    p].q[q]-     10     ){
  q++;}b=q-d;                         _=P                         [p].        d     ;
  if(b>_){/*]b                                                                */
   P[p].d=b;}{;                                                                }
   #undef/*pqdz'.*/  e//                                                      ;
   #define/*s8qdb]*/e/**/0                                                   //
   //<<.<<.----.>.<<.>++.++<                                              .[>]
   /*P[*/P[p].b++;continue;}}}t=                                       stdout;
  for (p=1;p<I;p++){/**/if(P[p].b>i                               ){i=P[p].b;}}
 if  (O){for(p=0;p<i;p++){q=0;/*[*/while(I               >++q){_=P[q].p-P[q ].q;
b=   0;if(_<P[q ].o){while(012-*P[q].p)     {putchar(*(P[q].p++));b++;}P[q]. p++;
}   ;while (P[  q].d>b++)putchar(040);}             putchar(10);}return 0;}p   =1;
   for(;   p<I   ;p++)fwrite(P[p] .q,P[              p].o,1,t);return 0 ;}//
  #/*]     ]<.    [-]<[-]<[- ]<[    -]<               [-  ]<;*/elif  e    //b
 |(1        <<     ( __LINE__        /*               >>   `*//45))  |     01U
             #                       /*               */     endif            //

這份code可以讓多個文件並排輸出。

你可以複製上面的這份code編譯看看(?)
(要把文件存成.c 不能是.cpp)

雖然很可愛(?)

解題流程

讀題

寫code

Debug

想算法

  • Code 邏輯能簡潔就簡潔,除非你很趕時間。

一個判斷奇偶不要這樣搞

#include <iostream>
using namespace std;
int main(){
    int n;
    cin >> n;
    for(int i=1; i<=n; i++)
        for(int j=0; j<n+i+2; j++)
            cout << (char)( (32*((j-n+i < 0) + !(j - n)) + (48 + i)* (j-n+i >= 0)* !!(j - n)) * !!(n+i+1-j) + 10*!(n+i+1-j) );
}

蛤?

893 - 數字塔 (是AC的。)

解題流程

讀題

寫code

Debug

想算法

  • 變數寫好看一點。 (去看一下codingStyle的投影片!!)
    • 避免用a, b, c, d, e, f...的命名方法,你到時候debug會看不懂😢

一個很靠北的範例

img ref: peipei

解題流程

讀題

寫code

Debug

想算法

  • 可以多使用註解來幫助自己回憶前面的code。
    • 例如把算法分成各個步驟,並用註解表示。
#include <iostream>
int main(){
    // Initialization
    int m, n, seat[10][10];
    
    // Input
    std::cin >> m >> n;
    for (int i=0; i<m; i++)
        for (int j=0; j<n; j++)
            std::cin >> seat[i][j];

    // Find called person
    int called, x, y;
    std::cin >> called;
    for (int i=0; i<m; i++)
        for (int j=0; j<n; j++) 
            if (seat[i][j] == called)
                x = i, y = j;

    // Find big cross
    int now_ans = 0;
    // Find row
    for(int i=0; i<n; i++)
        if(i != y && now_ans < seat[x][i])
            now_ans = seat[x][i];
    // Find column
    for(int i=0; i<m; i++)
        if(i != x && now_ans < seat[i][y])
            now_ans = seat[i][y];

    // print answer
    std::cout << now_ans << std::endl;
    return 0;
}
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/

當你程式的Logo (圖是libcurl的原始碼)

987 - 大十字的範例

解題流程

讀題

寫code

Debug

想算法

  • 要維護一些複雜的資料用struct
    • 例如你要維護每個學生的名字,成績,性別 ...
  • 常使用的邏輯丟到外面用function寫。
    • 例如判斷座標有沒有出界。
    • 或印出喵
  • 變數不要全部都塞在一行 (?)
    • 要用的時候再開就好。

解題流程

讀題

寫code

Debug

想算法

解題流程

讀題

寫code

Debug

想算法

寫完code可能的狀況?

AC

Accepted

WA

Wrong Answer

CE

Compile Error

RE

Runtime Error

TLE

Time Limit Exceeded

編譯錯誤

執行時期錯誤

超出時間限制

答案錯誤

過年囉

解題流程

讀題

寫code

Debug

想算法

AC

Accepted

WA

Wrong Answer

CE

Compile Error

RE

Runtime Error

TLE

Time Limit Exceeded

自己的解法錯誤

程式的邏輯錯誤

考慮非常奇怪的測資
(簡單上來說就是
反例構造)

怎麼盯著code冥想 ...
好像 ...
都找不到錯誤?

解題流程

讀題

寫code

Debug

想算法

AC

Accepted

WA

Wrong Answer

CE

Compile Error

RE

Runtime Error

TLE

Time Limit Exceeded

  • 光是已知的測資就錯了😭
    • 看錯誤輸出來猜可能會錯的原因。(格式?)
    • 帶入測資,從第一行code人腦編譯器。
    • 每個階段之間印出變數,看看是不是你所想的樣子? (cout大法!)
  • 測資都對丟上去OJ卻吃WA 🤔
    • 自己生測資啊不然哩
    • 自己寫一個生測資的程式來測試程式
  • 找朋友求助。 沒有就找朋友的朋友求助。

程式的邏輯錯誤

解題流程

讀題

寫code

Debug

想算法

AC

Accepted

WA

Wrong Answer

CE

Compile Error

RE

Runtime Error

TLE

Time Limit Exceeded

  • 自己編譯就錯了😢
    • 好好讀error message。
    • 把error message丟Google問一下。
    • 別糾結了,🈹,換個寫法吧。
  • 丟上去OJ卻吃CE 🤔
    • 多是版本問題,可以避免用太新的語法。
    • 別糾結了,🈹,換個寫法吧。

解題流程

讀題

寫code

Debug

想算法

AC

Accepted

WA

Wrong Answer

CE

Compile Error

RE

Runtime Error

TLE

Time Limit Exceeded

  • 常見RE問題
    • 除以0。 (其實也不是這麼常見)
    • 陣列索引超出範圍。
    • 陣列大小再開大一點點。
      • 例如字串要多1個空間給'\0'
    • 區域變數開太多。(例如在main開大大陣列)
    • 記憶體用太多爆掉了😢
    • 遞迴過深。
    • 指標問題。 (2!就會遇到了😢)

解題流程

讀題

寫code

Debug

想算法

AC

Accepted

WA

Wrong Answer

CE

Compile Error

RE

Runtime Error

TLE

Time Limit Exceeded

自己的解法錯誤

程式的邏輯錯誤

你確定你的解法真的不會TLE嗎?

  • 小心無窮迴圈
    • 例如for條件設錯
  • 沒有終止條件的遞迴
  • 程式寫得太複雜了...
    (俗稱卡常數)

評估方法: 參見 2!
第一堂課 - 時間複雜度

解題流程

Debug

De不到🐛就算了,時間有限,
去試試看其他題怎麼樣?

一些課後練習

我以前出的各式各樣可能很難的題目(?)

題目考的東西: 多維陣列 + 字串處理

解答: 投影片

題目考的東西: 看解題狀況好像有點難的字串處理

解答 (ver. WuJun Pei): 投影片 / 影片

解答 (ver. Arvin Liu): 投影片 / 影片

1! Review

By Arvin Liu

1! Review

  • 1,337