###### tags: `資訊科技`
# 程式設計(使用C++、ZeroJudge)
## 零、評量、學習歷程
### 1. 評量方式
+ 上課基本練習(遲交期限:1週) 50%
+ 期中上機考 20%
- 時間:三、迴圈教完後一週
- 上機考時網路會斷線,沒有任何參考資料,請每個子單元至少完成 1~2 題作業,熟練基本語法。
- 不要考前才寫作業,初學程式會有很多錯誤,要花時間除錯。請自我要求每週至少寫 1~2 題作業,上機考才會比較保險。
+ 期末上機考(六、函式教完後一週) 20%
- 時間:六、函式教完後一週或倒數第 2 週。
+ 解題報告 10%
- 想高分或上機考考差的同學請保握機會。
- 不會的可以去參考網路上的程式碼、解法,同學也可以互相討論,而且是鼓勵的。不論如何,都要在了解解法後,不看別人的程式碼,自己親自寫一遍。
- 中午電腦教室除考前1週外有開放時間,沒電腦、沒網路做作業的同學請善加利用。
- 繳交期限:
* 最後一週上課前1天。接近期末考,最慢在期中上機考後就要開始動工。
- 分數:
* 每一題10分,上限120分(12題)。
* 每個單元至多可放 2 題
* 不可以都寫同一單元的題目
* 題號劃掉的太簡單了,只是用來增加信心,不能放入解題報告。
- 報告格式:
* 第1頁為解題目錄(單元、題號、題目、頁碼)。
* 每題的子標題為
(1) 單元、題號、題目、題目簡述
(2) 解題動態、評分結果截圖
(3) 解題思路
(4) 程式碼
(5) 反思(遇到的錯誤、修正的地方、更好的方法…)
(6) 錯誤程式碼
- 檢核方式:
* 有交解題報告者,最後一週會請你在沒有網路的狀態下重寫一題當做檢核(題目由老師挑選),寫不出來作業直接作廢不算分,請務必自行思考完成。
* 不要為了分數直接複製貼上別人的程式碼,那是無意義的行為,檢核時你就會現出原形,就不用做這種白工了。
- 可整合上課內容後完成課程學習成果,上傳至學習歷程檔案平台。請儘量挑選一開始有錯,然後修正的題目,將修正的想法寫出來更能顯示出反思的能力。
- 如果對寫程式有興趣並要參加APCS檢定,下學期多元選修可以選修APCS(大學程式設計先修檢測)程式實作,挑選標準主要為ZJ的解題數(請寫在多元選修意向書裏)。
### 2. [TOI推廣計畫-線上練習賽](https://tpmso.org/toi/index.php/reg/)
+ 成績計算:分數/100直接加在總成績。
+ 上學期10、11、12月,下學期3、4、5月,最後一週。
+ 星期一08:00 ~ 星期五20:00。90分鐘。
+ [證書](https://drive.google.com/open?id=1DcgDKn1R33kOPc_HazdIyQDgyYxSCPlZ)
### 3. [APCS](https://apcs.csie.ntnu.edu.tw/)
+ 實作級分*2,直接加在總成績。
+ 3級分免上機考,上機考成績為100。
+ 4級分以上者,一切皆免,學期成績直接算100。
### 4. 學習歷程檔案(修課記錄、課程學習成果)
+ 最後一週上課結束前如果認證完成,學期總成績加分。
+ [撰寫「課程學習成果」參考資源](https://hackmd.io/@cube/HkCv90e19)。
### 5. 基礎教學網站
+ [基礎程式設計 - C與C++簡報、影片](http://www.18dice.tw/diceweb/teacherstudy/CandC++.html)
### 6. [SoloLearn C++ Tutorial](https://www.sololearn.com/)
+ 全部學完可拿到[證書](https://i.imgur.com/0yAAPlB.jpg)(額外加分)。
### 7. 軟體
+ [Code::Blocks](http://cs.cysh.cy.edu.tw/software/software_download.html)
+ [Dev-C++](http://cs.cysh.cy.edu.tw/software/software_download.html)
+ [VSCode](https://hackmd.io/@liaojason2/vscodecppwindows )([無法debug處理](https://stackoverflow.com/questions/37405975/c-for-vs-code-unable-to-start-debugging-program-path-is-missing-or-invalid?fbclid=IwAR1QQOzXkI6LQc2n0L3q0Sywp_Fx92igG83ngDbhLJrMdZXvaFEqtOW04hM))
+ [GDB online Debugger | Compiler - Code, Compile, Run, Debug online C, C++](https://www.onlinegdb.com/)
+ [The collaborative browser based IDE - Replit](https://replit.com/)
## 一、輸出與輸入、變數、運算式與運算子
### 1. 輸出與輸入
:::info
EX_1_1:[d483: hello, world](https://zerojudge.tw/ShowProblem?problemid=d483)
+ 快速鍵
`Ctrl+滾輪`:放大、縮小
`F9`:Build and run
`Ctrl+a`:全選
`Ctrl+c`:複製
`Ctrl+v`:貼上
`Ctrl+x`:剪下
:::
:::info
EX_1_2:[a001: 哈囉](https://zerojudge.tw/ShowProblem?problemid=a001)
``` c
int main()
{
~ // 變數宣告
while(cin >> ~) //不需要加「;」
{
cout << ~ << endl;
}
return 0;
}
```
+ 快速鍵
`Shift`+方向鍵、`Home`、`End`:選取程式
+ 執行完的測試視窗要關閉,才能再次執行。
:::
### 2. 變數型態
| 常用型態 | 意義 | 範圍 |
|:-------|:---------- |:-------|
| int | 整數 |-2147483648~2147483647||
| long long int | 長整數 |-2^63^ ~ 2^63^-1||
| float | 單精度浮點數(小數) |±1.5x10^−45^ ~ ±3.4x10^38^|
| double | 雙精度浮點數(小數) |±5.0×10^−324^ ~ ±1.7×10^308^|
| char | 字元 | 'A'|
| string | 字串 | "Hello"|
| bool | 布林 | true、false|
### 3. 變數宣告
``` c
int math=80; // 資料型態 變數名稱;
double pi=3.14159265359; // 資料型態 變數名稱=初值;
int sum,ave,rank; // 資料型態 變數名稱1,變數名稱2,變數名稱3...;
```
:::info
EX_1_3:[a002: 簡易加法](https://zerojudge.tw/ShowProblem?problemid=a002)
+ cin >> a,b; 是錯誤的語法。
+ 使用線上軟體或再開一個專案(homework)寫作業,未寫完存雲端。
:::
:::info
EX_1_4:[d489: 伏林的三角地](https://zerojudge.tw/ShowProblem?problemid=d489)
+ 以[海龍公式](https://zh.wikipedia.org/zh-tw/%E6%B5%B7%E4%BC%A6%E5%85%AC%E5%BC%8F)求三角形面積。
+ 「*」不可省略。
+ 先乘除後加減,可用小括號改變運算順序。
+ // 註解
+ 需除錯時,可將變數印出來看。
+ cin >> a >> b >> c >> s → error,s不用輸入
:::
:::warning
[~~d049: 中華民國萬歲!~~](https://zerojudge.tw/ShowProblem?problemid=d049)
:::
:::warning
[a861: 1. Secure the Perimeter](https://zerojudge.tw/ShowProblem?problemid=a861)
:::
:::warning
[c379: 成為出題者](https://zerojudge.tw/ShowProblem?problemid=c379)
:::
:::warning
[d461: 班際籃球賽](https://zerojudge.tw/ShowProblem?problemid=d461)
:::
:::warning
[d053: 10970 - Big Chocolate](https://zerojudge.tw/ShowProblem?problemid=d053)
:::
### 4. 算數運算子
| 算數運算子 | 意義 | 備註|
|:-------- |:------ |:-------|
| + | 加 | |
| - | 減 | |
| * | 乘 | |
| / | 除 | |
| % | 取餘數 | |
| ++ | 遞增 | i++ 即 i=i+1|
| \-\- | 遞減 | i\-\- 即 i=i-1|
:::info
EX_1_5:[d050: 妳那裡現在幾點了?](https://zerojudge.tw/ShowProblem?problemid=d050)
+ %
:::
:::info
EX_1_6:[d485: 我愛偶數](https://zerojudge.tw/ShowProblem?problemid=d485)
+ 將 a 調整為後一個偶數, b 為前一個偶數,[計算等差數列項數](https://zh.wikihow.com/%E8%AE%A1%E7%AE%97%E7%AD%89%E5%B7%AE%E6%95%B0%E5%88%97%E4%B8%AD%E7%9A%84%E9%A1%B9%E6%95%B0)。
+ a 偶數 a=a+0,a 奇數 a=a+1
- a=a+a%2
+ 複合指定運算子(a=a+5 → a+=5)
:::
:::info
EX_1_7:[d051: 糟糕,我發燒了!](https://zerojudge.tw/ShowProblem?problemid=d051)
+ (f-32)*5/9
+ 整數除法、浮點數除法:5/2、5.0/2。
+ 型態轉換(double)。
+ C++小數點位數控制。
+ f,c 全部宣告為 double?
- double 不可 %。
``` c
#include <iomanip>
cout << fixed << setprecision(3) << ... ;
// setprecision(n) 會將輸出的數值控制為 n 位數,如果加上 fixed 表示只控制小數點以下的位數。
```
:::
:::warning
[d073: 分組報告](https://zerojudge.tw/ShowProblem?problemid=d073)
+ / 整數除法
:::
:::warning
[d827: 買鉛筆](https://zerojudge.tw/ShowProblem?problemid=d827)
+ %
:::
:::warning
[b757: 頸美椰子樹](https://zerojudge.tw/ShowProblem?problemid=b757)
+ double
+ /
:::
:::warning
[a862: 2. My Dear Friend VIR](https://zerojudge.tw/ShowProblem?problemid=a862)
+ double
+ /
+ C++小數點位數控制。
:::
:::warning
[f651: 開關燈](https://zerojudge.tw/ShowProblem?problemid=f651)
+ / 整數除法
+ 觀察n=1~10,找規律。類似d073。
:::
### 5. 關係運算子
| 關係運算子 | 意義 | 備註|
|:-------- |:------ |:-------|
| == | 等於 | =是指派,==是判斷是否相等 |
| != | 不等於 |
| > | 大於 |
| >= | 大於等於 |
| < | 小於 |
| <= | 小於等於 |
:mega: a < b < c 要寫成 a < b && b < c
### 6. 邏輯運算子
| 邏輯運算子 | 意義 | 備註|
|:-------- |:------ |:-------|
| && | and |
| \|\| | or |
| ! | not |
:::info
EX_1_8:[d063: 0 與 1](https://zerojudge.tw/ShowProblem?problemid=d063)
+ !
:::
:::info
EX_1_9:[e343: BMI 計算](https://zerojudge.tw/ShowProblem?problemid=e343)
+ 運算式中沒有中、大括號,通通都用小括號。
+ 型態轉換。
+ C++小數點位數控制。
+ 需除錯時,可將變數印出來看。
:::
## 二、選擇
### 1. if 條件式語法
``` c
if(條件)
{
條件「成立」時的程式碼
}
```
:mega: if()後不能加「;」
:::info
EX_2_1:[a012: 10055 - Hashmat the Brave Warrior](https://zerojudge.tw/ShowProblem?problemid=a012)
+ long long
+ Q:cout << ans << endl; 放在if{ }內會發生什麼問題?
:::
:::warning
[~~a799: 正值國~~](https://zerojudge.tw/ShowProblem?problemid=a799)
:::
:::warning
[d068: 該減肥了!](https://zerojudge.tw/ShowProblem?problemid=d068)
:::
:::warning
[b682: 2. 同學早安](https://zerojudge.tw/ShowProblem?problemid=b682)
+ [提示](https://zerojudge.tw/ShowThread?postid=16450&reply=0)
+ 將時間全部轉成分鐘會比較好做,分鐘的時間差以/、%轉回小時、分。
+ 因為校長最久只會站23小時59分,所以如果開始時間大於結束時間,表示站隔夜,結束時間要多加1440。
:::
:::warning
[h658: 捕魚 (Fishing)](https://zerojudge.tw/ShowProblem?problemid=h658)
+ d(距離)及minD(最小距離)要宣告為double,minD的初值可假設為一個比可能最大值還要大的值(如1000)。
+ 開根號用sqrt(),需含入 cmath 標頭檔,d=sqrt((x-a)\*(x-a)+(y-b)\*(y-b));
+ 讀入每個魚群的中心座標,計算魚夫和魚群的距離,如果比目前的最小距離小,則記錄此時的最小距離和座標。
:::
### 2. if~else 語法
``` c
if(條件)
{
條件「成立」時的程式碼
}
else
{
條件「不成立」時的程式碼
}
```
:mega: 養成縮排的好習慣:大括號 { } 內的程式碼以Tab鍵向右縮排,可以增加程式碼的可讀性,並方便除錯。
:::info
EX_2_2:[d064: ㄑㄧˊ 數?](https://zerojudge.tw/ShowProblem?problemid=d064)
:::
:mega: [常用運算子的優先順序](https://magicjackting.pixnet.net/blog/post/70902861)
:::info
EX_2_3:[d066: 上學去吧!](https://zerojudge.tw/ShowProblem?problemid=d066)
+ 7<=h<17
→ h>=7 && h<17
→ h>=7 && m>=30 && h<17,幾點會造成錯誤?
→ (h>=8 && h<17) || (7點的狀況)
+ &&、||
:::
:::warning
[b877: 我是電視迷](https://zerojudge.tw/ShowProblem?problemid=b877)
:::
:::warning
[f373: 週年慶 Anniversary](https://zerojudge.tw/ShowProblem?problemid=f373)
+ 題目簡述
- 天天百貨(編號0)消費滿2000折200,琪琪百貨(編號1)消費滿1000折100。
- 輸入一正整數 N (0 ≦ N ≦ 10000),代表預計花費的金額,請問去那個百貨可以得到最好的優惠(如果優惠後的價格一樣,預設去天天百貨)。
- 輸出折扣後的金額以及百貨的編號。
+ 分別計算兩百貨折扣後的金額,比較大小輸出。
:::
:mega: 如果測資的第一行有一個整數t,代表測試的筆數,要用以下的寫法。
```cpp=
cin >> t;
while(t>0)
{
~
t--;
}
或
cin >> t;
while(t--)
{
~
}
```
:::warning
[e948: 1. 基礎代謝率 (BMR Calculation)](https://zerojudge.tw/ShowProblem?problemid=e948)
+ 輸入的第一行有一個整數n,代表測試筆數。while(n--) // 兩個減號,[寫法參考](https://yuihuang.com/zj-e948/)
+ C++小數點位數控制。
``` c
#include <iomanip>
cout << fixed << setprecision(2);
```
:::
:::warning
[f043: 1. 小豪的回家作業 (Homework)](https://zerojudge.tw/ShowProblem?problemid=f043)
+ 給定兩整數R、A,求出A+B=R的B值後輸出。
+ 如果R=A,則先將A-3再求B。
+ A、B小的寫在算式的前面。
:::
### 3. 巢狀 if 語法
``` c
if(條件1)
{
if(條件2)
{
條件1「成立」,且條件2「成立」時的程式碼
}
else
{
條件1「成立」,且條件2「不成立」時的程式碼
}
}
else
{
條件1「不成立」時程式碼
}
```
:mega: if或else的大括號{ }內,都可再增加條件式。
:::info
EX_2_4:[d058: BASIC 的 SGN 函數](https://zerojudge.tw/ShowProblem?problemid=d058)
+ if(n>0) vs. if(n>=0)
:::
:::info
EX_2_5:[a006: 一元二次方程式](https://zerojudge.tw/ShowProblem?problemid=a006)
+ 開根號用sqrt(),需含入 cmath 標頭檔。
+ d=0時,x1還是要計算過程。執行時,不會去執行不符合條件的程式碼。
+ F8除錯示範。
+ Q:x1、x2放在d後面計算可以嗎?負數開根號?
:::
:::warning
[a003: 兩光法師占卜術](https://zerojudge.tw/ShowProblem?problemid=a003)
:::
:::warning
[d065: 三人行必有我師](https://zerojudge.tw/ShowProblem?problemid=d065)
:::
:::warning
[f165: 棒棒糖事件](https://zerojudge.tw/ShowProblem?problemid=f165)
+ 判斷棒棒糖數除以小朋友人數的餘數r是否為0,當r=0時,輸出「OK!」,反之輸出r。
+ 小朋友人數可能為0,不會搶成一團,所以蝸牛老師不需吃下任何棒棒糖,輸出「OK!」。
+ 先排除小朋友人數為0的狀況,不然「%」運算會錯誤。
:::
:::warning
[b899: 2. 物品探測](https://zerojudge.tw/ShowProblem?problemid=b899)
+ 分別計算三點間的距離,最長的為正方形的對角線。
+ 正方形四點 A、B、C、D,假設 A、C 為對角,則 D = A + C - B。
:::
### 4. 多重選擇 if~else if~else 語法
``` c
if(條件1)
{
條件1「成立」時程式碼區塊
}
else if(條件2)
{
條件1「不成立」,且條件2「成立」時的程式碼
}
else if(條件3)
{
條件1、2「不成立」,且條件3「成立」時的程式碼
}
...
else
{
上述條件都「不成立」時的程式碼
}
```
:mega: else if()可視需要增加。
:::info
EX_2_6:[d460: 山六九之旅](https://zerojudge.tw/ShowProblem?problemid=d460)
:::
:::warning
[f337: 同樂會 (Party)](https://zerojudge.tw/ShowProblem?problemid=f337)
:::
:::warning
[c382: 加減乘除](https://zerojudge.tw/ShowProblem?problemid=c382)
+ 要宣告一個字元變數(char)讀「+ - * /」,比較時,字元前後要有單引號。
:::
:::warning
[b676: 63萬勞工苦輪班不像人像機器](https://zerojudge.tw/ShowProblem?problemid=b676)
:::
:::warning
[a053: Sagit's 計分程式](https://zerojudge.tw/ShowProblem?problemid=a053)
:::
:::warning
[a244: 新手訓練 ~ for + if](https://zerojudge.tw/ShowProblem?problemid=a244)
+ long long
+ while(n--)
:::
:::warning
[e972: 1. 貨幣轉換 (Currency)](https://zerojudge.tw/ShowProblem?problemid=e972)
+ 變數可設為double。
+ 先將預算轉成目的地的幣值。
+ 依「預算<花費」,「預算-花費<0.05」(0.00以字串列印->"0.00"),「預算>花費」,分別輸出。
+ C++小數點位數控制。
``` c
#include <iomanip>
cout << fixed << setprecision(2) << money-m;
```
:::
## 三、迴圈
### 1. for 迴圈語法
``` c
for(變數初值; 條件判斷; 改變量)
{
程式碼
}
```
:mega: 除錯練習
(1) Build and run (F9)後發現錯誤
(2) 設中斷點
(3) Debug (F8) (程式會執行到中斷點後停止,讓我們可以按 F7 逐行執行)
(4) Debugging windows/Watches
(5) Next line (F7) (行號旁出現黃色箭頭開始按 F7,黃色箭頭的這一行表示按 F7 後要執行)
(6) Stop debugger
:::info
EX_3_1:[d498: 我不說髒話](https://zerojudge.tw/ShowProblem?problemid=d498)
``` c
int i;
for(i=1; ...)
{
}
```
Q1:如果改變量寫i+1,會發生什麼事,練習除錯(F8)。
+ i=i+1 或 i+=1 或 i++
+ i+1不會改到i
Q2:n輸入10,以除錯(F8)看流程,當n=10時,下一行會往上或往下執行?i 最後的值為?
Q3:n=10時,i+=3(i=i+3),會印出幾次字串, i 最後的值為?
:::
:::info
EX_3_2:[d490: 我也愛偶數](https://zerojudge.tw/ShowProblem?problemid=d490)
Q1:先完成 a+...+b,但答案會錯誤?
+ 先將 i、sum 印出來看,或除錯(F8)。
+ 初值歸零
Q2:初值歸零後,第2次答案會錯誤?
+ 變數範圍:int sum=0; // 宣告在while迴圈內
+ 區塊變數:for(int i=a;)
:::
:::warning
[~~b970: 我不說髒話 (續)~~](https://zerojudge.tw/ShowProblem?problemid=b970)
:::
:::warning
[d046: 文文採西瓜](https://zerojudge.tw/ShowProblem?problemid=d046)
:::
:::warning
[d786: 三、平均值](https://zerojudge.tw/ShowProblem?problemid=d786)
+ 每筆測資sum要歸零。
:::
:::warning
[c005: 10300 - Ecological Premium
](https://zerojudge.tw/ShowProblem?problemid=c005)
+ long long
+ 運算式可先化簡避免除法誤差。
:::
:::warning
[f708: 蟲蟲危機 (Insect)](https://zerojudge.tw/ShowProblem?problemid=f708)
+ 題目簡述
- 第一行有整數 M 和 N (1 ≤ M ≤ 2000, 1 ≤ N ≤ 2000) 代表螞蟻和蚱蜢的總數
- 第二行有 M 個數字表示螞蟻的身高 Ai (1 ≤ Ai ≤ 1000, 1 ≤ i ≤M)
- 第三行有 N 個數字表示蚱蜢的身高 Gi (1 ≤ Gi ≤ 1000, 1 ≤ i ≤ N)
- 若螞蟻的數量比蚱蜢多且螞蟻的總身高比蚱蜢高,螞蟻們才敢決定跟蚱蜢打一架爭,輸出 Yes,否則輸出 No。
:::
:::warning
[f338: 后羿射日(Archer)](https://zerojudge.tw/ShowProblem?problemid=f338)
:::
:::warning
[j178: 手遊廣告 (Advertisement)](https://zerojudge.tw/ShowProblem?problemid=j178)
+ break:強制跳出「整個」迴圈。
:::
:::warning
[f312: 1.人力分配](https://zerojudge.tw/ShowProblem?problemid=f312)
+ 以for迴圈枚舉所有可能的工人分配方法。
+ 求最大值可用max函式或if。
:::
:::warning
[f605: 1. 購買力](https://zerojudge.tw/ShowProblem?problemid=f605)
+ 找出3物品最大值和最小值,可使用if或max、min函式。
+ max 若要傳入三個以上的參數,須用大括號包住,並含入 algorithm 標頭檔。
:::
:::warning
[c299: 1. 連號或不連號](https://zerojudge.tw/ShowProblem?problemid=c299)
+ 輸入數列時,找出其最大值和最小值,可使用if或max、min函式。
+ 最大-最小+1==n,表示這個數列是連續的。
:::
:::warning
[d660: 11764 - Jumping Mario](https://zerojudge.tw/ShowProblem?problemid=d660)
+ prev=now
:::
### 2. 巢狀迴圈語法
``` c
for(變數1初值;條件1判斷;改變量)
{
for(變數2初值;條件2判斷;改變量)
{
程式碼
}
}
Q:在日常生活中,有什麼事像巢狀迴圈的概念?
```
:::info
EX_3_3:[c418: Bert的三角形 (1)](https://zerojudge.tw/ShowProblem?problemid=c418)
:::
:::info
EX_3_4:[c419: Bert的三角形 (2)](https://zerojudge.tw/ShowProblem?problemid=c419)
+ 除錯練習:內圈若寫j--會如何?
:::
:::warning
[c420: Bert的三角形 (3)](https://zerojudge.tw/ShowProblem?problemid=c420)
:::
:::warning
[f063: The Strongest Chain](https://zerojudge.tw/ShowProblem?problemid=f063)
+ 巢狀迴圈。
+ 求每條鏈子最小值中,找出最大值。
:::
:::warning
[c013: 00488-Triangle Wave](https://zerojudge.tw/ShowProblem?problemid=c013)
+ 巢狀迴圈。
+ 下半部 for(k=A-1;k>0;k\-\-)
:::
### 3. while 迴圈語法
``` c
while(條件判斷) // 條件為「真」的時候繼續執行
{
程式碼
}
```
``` c=
for(int i=1;i<=5;i++)
{
cout << "hello ";
}
cout << endl;
int i=1;
while(i<=5)
{
cout << "hello ";
i++;
}
```
:::info
EX_3_5:[d189: 11150 - Cola](https://zerojudge.tw/ShowProblem?problemid=d189)
+ 請用 while 模擬換瓶過程,不可以直接套公式。
+ 以除錯(F8)看換瓶過程,最後剩 2 空瓶,可借 1 空瓶多換 1 瓶。
``` c=
int sum=n;
while()
{
}
if(n==2)
{
sum++;
}
```
+ 題目先借瓶,什麼狀況需要借?
→ 不管需不需要都借。為什麼 n=9 時,不需要借也借,卻不會錯誤。(F8)
``` c=
int sum=n;
n++;
while()
{
}
```
:::
:::info
EX_3_6:[a038: 數字翻轉](https://zerojudge.tw/ShowProblem?problemid=a038)
+ 前面有 0 的話應消除。如50200 不是輸出 00205,而是205。
+ 0要輸出0。為何會TLE?除錯(F8)練習。
+ 迴圈中斷
- break:強制跳出「整個」迴圈。
- continue:強制跳出「此次」 迴圈,繼續進入下一次圈。
``` c==
for(int i=1;i<=10;i++)
{
if(i==5)
{
break; // continue;
}
cout << i << " ";
}
```
:::
:::warning
[c079: 10346 - Peter's Smokes](https://zerojudge.tw/ShowProblem?problemid=c079)
:::
:::warning
[d570: 神龍見首不見尾](https://zerojudge.tw/ShowProblem?problemid=d570)
:::
:::warning
[f070: 1. 韓信點兵 (HanXin)](https://zerojudge.tw/ShowProblem?problemid=f070)
+ 因為答案很小,暴力解即可。
+ while(true),從1開始測,輸出符合條件的值。
:::
:::warning
[c350: “綠白黃” 四校聯課](https://zerojudge.tw/ShowProblem?problemid=c350)
+ ans+=(n/k)*w; // 每次新換的電話號碼
+ n-=(n/k)*(k-w); // 因為 k > w,所以可以看成每一次的交換(k換w),新號碼會減少 (k-w) 個。
:::
### 4. do..while 迴圈語法
``` c
do
{
程式碼
}while(條件判斷); // 條件為「真」的時候繼續執行
```
:mega: do while()後要加分號!
:::info
EX_3_7:[d356: NOIP2002 1.级数求和](https://zerojudge.tw/ShowProblem?problemid=d356)
+ 型別轉換。
+ 浮點數誤差(float->double)。
+ cout << --i << endl;
``` c
int a=1,b;
b=a++;
b=++a;
cout << a << " " << b << endl;
```
:::
:::info
EX_3_8:[a149: 乘乘樂](https://zerojudge.tw/ShowProblem?problemid=a149)
+ 假設 n 固定只有3位數,練習求百位、十位、個位數字。
+ mul*=n%10 vs. mul=mul*n%10 (錯誤)
+ [常用運算子的優先順序](https://magicjackting.pixnet.net/blog/post/70902861)
+ 以while迴圈改寫會發生什麼錯誤?
:::
:::warning
[a215: 明明愛數數](https://zerojudge.tw/ShowProblem?problemid=a215)
:::
:::warning
[c561: Bert 愛搗蛋](https://zerojudge.tw/ShowProblem?problemid=c561)
+ 將數字反轉,記錄最大值。
+ 將數值反轉的方法,假設 a為原數值,rvs為反轉後的數值(預設值為 0)
rvs=rvs*10+(a%10);
a/=10; // 讓個位數消失
:::
:::warning
[f374: 分組 Grouping](https://zerojudge.tw/ShowProblem?problemid=f374)
:::
## 四、陣列
### 1. 陣列宣告
``` c
int a[5]; // 宣告一個大小為5的int陣列
a[0]=80; // 陣列的索引值由0開始
a[5]=90; // 錯誤,索引值0~4
int a[5]={1,3,5,7,9}; // 宣告陣列時設定初值
int a[5]={1}; // a[0]初值1,其餘預設為0
for(int i=0;i<5;i++) // 以 for 迴圈來控制陣列的 index
cin >> a[i];
// 1-based indexing
int a[6];
for(int i=1;i<=5;i++) // 以 for 迴圈來控制陣列的 index
cin >> a[i];
int a2d[4][2]; // 宣告二維陣列(多維陣列)
int a2d[4][2]={{1,2},{3,4},{5,6},{7,8}};
Q:如何建立可以儲存班上期中考成績的二維陣列?
// a2d[r][c]表示第 r 列,第 c 欄的值(類似英文書寫習慣)
```
:::info
EX_4_1:[b127: 會議中心(Room)](https://zerojudge.tw/ShowProblem?problemid=b127)
+ [費式數列](https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97)
:::
:::info
EX_4_2:[a693: 吞食天地](https://zerojudge.tw/ShowProblem?problemid=a693)
+ [陣列宣告時,大小請直接指定為題目給的最大範圍,避免用變數。](https://openhome.cc/Gossip/CGossip/OneDimArray.html)
``` c
int n;
while(cin >> n >> m)
{
int food[n]; // 避免使用,編譯器不一定支援。
int food[100005];
}
```
+ 每次都重算會TLE。檔名:a693(TLE)
+ [時間複雜度](https://jason-chen-1992.weebly.com/home/time-space-complexity)
+ [前綴和](https://www.youtube.com/watch?v=VfL7dzFkW30),不要用爆力法
``` c
for(int i=1;i<=n;i++) // 對每個idx
{
for(int j=1;j<=i;j++) // 從頭開始加到此idx
{
pfx[i]+=food[j]
}
}
```
+ i=0時,food[i]=food[i-1]+t 會錯誤,所以改從index 1 開始放前綴和。
- [1-based indexing](https://xlinux.nist.gov/dads/HTML/oneBasedIndexing.html)
:::
:::info
EX_4_3:[i071: 風景 (Landscape)](https://zerojudge.tw/ShowProblem?problemid=i071)
+ [1-based indexing](https://xlinux.nist.gov/dads/HTML/oneBasedIndexing.html)
+ 從小明家往左、往右檢查>小明家樓高的數量,錯誤的原因為?
+ 以變數(LMax、RMax)記錄小明家左邊、右邊最高樓高(初值為小明家樓高)。從小明家往左、往右檢查,如果檢查的樓高>LMax、RMax,則答案+1,並調整LMax、RMax。
+ 或往右發現有比小明家高的樓高,就讓小明家長高,或讓小明搬家。(小明家高要先保留,往左檢查前要恢復原高)
+ for迴圈的計數變數來控制陣列存取的位置。
``` c
for(int i=1;i<=n;i++)
cin >> h[n]; // 錯誤
```
:::
:::warning
[f345: 新手練習題—陣列](https://zerojudge.tw/ShowProblem?problemid=f345)
:::
:::warning
[b138: NOIP2005 1.陶陶摘苹果](https://zerojudge.tw/ShowProblem?problemid=b138)
:::
:::warning
[f818: 物競天擇 (Survival)](https://zerojudge.tw/ShowProblem?problemid=f818)
+ 設一個變數存身高*體重的最小值,初值為1000005。
:::
:::warning
[e339: 前綴和練習](https://zerojudge.tw/ShowProblem?problemid=e339)
+ 累加的數值會超過 int 上限。
+ 若使用陣列記錄,小心不要出現b[-1]的狀況。
:::
:::warning
[b558: 求數列第 n 項](https://zerojudge.tw/ShowProblem?problemid=b558)
:::
:::warning
[f442: 老鷹抓小雞 Eagle](https://zerojudge.tw/ShowProblem?problemid=f442)
+ 題目簡述
- 「老鷹抓小雞」的遊戲玩法為有一人是老鷹、一人是母雞、剩下的人為小雞(老鷹要抓小雞,母雞則要保護身後的小雞)。小雞被抓後會變成老鷹,老鷹則變成小雞(取代被抓小雞的位置)。
- 第一列有一正整數 N,代表有 N 隻小雞。
- 第二列有 N 個正整數,代表小雞的編號。
- 第三列有一正整數 E,代表老鷹的編號。
- 第四列有一正整數 Q,代表玩了 Q 回合。
- 第五列有 Q 個正整數,代表每回合被抓到小雞的編號。
- 輸出經過 Q 回合後,隊伍中小雞的編號。
:::
:::warning
[b139: NOIP2005 2.校门外的树](https://zerojudge.tw/ShowProblem?problemid=b139)
+ 可以宣告一個整數陣列tree(預設為0),陣列的索引值代表位置,陣列值0、1表示有沒有樹。
:::
:::warning
[a253: 王老先生的磨菇田](https://zerojudge.tw/ShowProblem?problemid=a253)
+ 因為蘑菇編號只介於0~100間,因此可以開一個大小為101的陣列(初始值皆為0),陣列的索引值代表蘑菇編號,儲存對應編號的蘑菇數量。
:::
:::warning
[b374: [福州19中]众数](https://zerojudge.tw/ShowProblem?problemid=b374)
+ [想法參考](https://zerojudge.tw/ShowThread?postid=16300&reply=0)
:::
:::warning
[c199: 爬山去(Hiking)-TOI練習賽y7m5-1](https://zerojudge.tw/ShowProblem?problemid=c199)
+ 輸入時可先將重覆的數字去掉。
:::
:::warning
[g308: pB. 跳跳布朗尼(Brownie)](https://zerojudge.tw/ShowProblem?problemid=g308)
+ 使用布林陣列來記錄每個格子是否普經走過。
+ 亦可直接使用記錄「傳送點資訊」的陣列,走過就設為「-1」。
:::
### 2. 二維陣列
:::info
EX_4_4:[a694: 吞食天地二](https://zerojudge.tw/ShowProblem?problemid=a694)
+ 前綴和 ![](https://hackmd.io/_uploads/r1vpzDlSn.png) **➜** ![](https://hackmd.io/_uploads/BJMRGvlr3.png)
+ [如何以a693的方式加速?](https://sites.google.com/a/mail.hpsh.tp.edu.tw/pc/jiao-cai/a694-tun-shi-tian-de-er)
|[0][0] |[0][1]|[0][2] |[0][3] |[0][4]|[0][5] |
|:----: |:----:|:----: |:----: |:----:|:----: |
|**[1][0]**| | | | | |
|**[2][0]**| |[r1-1][c1-1]| | |[r1-1][c2]|
|**[3][0]**| | |[r1][c1]| | |
|**[4][0]**| | | | | |
|**[5][0]**| |[r2][c1-1] | | |[r2][c2] |
+ 陣列初值設為0
``` c
#include <cstring>
memset(a,0,sizeof(a));
```
+ [C++ IO加速](https://blog.csdn.net/YinJianxiang/article/details/76436089)([原始網站](http://chino.taipei/note-2016-0311C-的輸出入cin-cout和scanf-printf誰比較快?/))
``` c
ios::sync_with_stdio(false);
cin.tie(0);
```
:::
:::info
EX_4_5:[e798: p5. 卷積神經網路](https://zerojudge.tw/ShowProblem?problemid=e798)
+ 求最大值可用max函式或if。
+ max 若要傳入三個以上的參數,須用大括號包住([initializer_list](https://blog.csdn.net/ko_tin/article/details/68190364)),並含入 algorithm 標頭檔。
:::
:::warning
[b367: 翻轉世界](https://zerojudge.tw/ShowProblem?problemid=b367)
+ 假設 a180 為 a 轉 180 度後的陣列,a[i][j] 轉180度後會放在 a180[r-i-1][c-j-1];
:::
:::warning
[f513: 舉旗遊戲 (Flag)](https://zerojudge.tw/ShowProblem?problemid=f513)
+ 題目簡述
- 第一列有兩正整數 R、C(3 ≦ R、C ≦ 100),表示有 R×C 個人排成 R 列 C 行。
- 接著輸入 R 列,每列有 C 個正整數(1或2),代表每個人旗子的編號。
- 如果某人周遭的八個人,旗子的編號跟他都不一樣,則該人就被淘汰。請問有多少人會被淘汰?
+ 陣列行、列可多開2個空間,index 0不要用,以免有些點的相鄰點會超出陣列。
+ 如果自己的顏色和相鄰 8 點都不同,則淘汰人數+1。
``` c
if(a[i][j]!=a[i-1][j-1] && a[i][j]!=a[i-1][j] && a[i][j]!=a[i-1][j+1] && a[i][j]!=a[i][j-1] && ...)
// 左上、上、右上、左
cnt++;
```
:::
:::warning
[f418: Word Search Puzzle](https://zerojudge.tw/ShowProblem?problemid=f418)
+ char a[25][55];
+ 不會有起始點在下,終點在上面的單字。
+ 總共只有3種情況
- r1==r2 橫著印
- c1==c2 直著印
- 其它斜著印,從(r1+1,c1+1),(r1+2,c1+2)......印到(r1+(r2-r1-1),c1+(c2-c1-1)),(r2,c2)
:::
:::warning
[e787: b2.尋寶地圖(Map)](https://zerojudge.tw/ShowProblem?problemid=e787)
+ 轉換圖計算行、列和時,重複算的要扣除。
+ [題目](https://tpmso.org/toi/wp-content/uploads/question/201912/B2-Map.pdf)
+ [解題參考](https://tpmso.org/toi/wp-content/uploads/question/201912/B2-Map.pptx)
:::
:::warning
[f737: 農地 (Farmland)](https://zerojudge.tw/ShowProblem?problemid=f737)
+ 類似 a694 的方法,以前綴和的方式計算(1,1)到每個點的總成本,-1不能開墾,可以將其值設為比開墾總預算大的值。
+ 針對每個點,窮舉計算所有邊長的正方形農地的成本和。
+ 因為只要知道最大的開墾面積,所以每次計算可從目前最大邊長+1開始即可。如果點座標+邊長超出邊界,或成本和 > 總預算,則之後的邊長都不用再檢查。
+ C++ IO加速。
+ [解題參考](https://tpmso.org/toi/wp-content/uploads/question/202103/Farmland.odp)
:::
:::warning
[a867: 7. Minelayer](https://zerojudge.tw/ShowProblem?problemid=a867)
+ 可以從index 1 開始放,想像盤面最外圍包了一圈0,例如3x5的盤面:
0000000
0●●\*●\*0
0\*\*●●●0
0●\*\*●●0
0000000
+ 宣告二維的字元陣列
char mine[17][32]={0};
int cnt[16][31]={0};
+ 不需最外層的while()
:::
:::warning
[f148: 2. 定向越野 (Orienteering)](https://zerojudge.tw/ShowProblem?problemid=f148)
+ 可以宣告一個 arr[26][3] 的二維陣列,初值均為 0。
- 26 表示有 26 個字母,a 對應到index 0、b 對應到index 1 …
- arr[ ][0]存字母是否存在,arr[ ][1]存列座標,arr[ ][2]存欄座標。
- 例如讀到 'a' 位於(0,2)
arr[c-'a'][0]=1;
arr[c-'a'][1]=0;
arr[c-'a'][2]=2;
+ 當讀取的地圖字元不是'0' 時,標記此字元存在,記錄其座標,並累計目標數量。
+ 如果目標數量<N,輸出"Mission fail."。否則從陣列 0 開始判斷該位子對應的字元是否存在,如果存在則輸出座標,直到滿 N 個目標。
:::
## 五、字串(字元陣列)
### 1. 字串宣告
``` c
int a[3]={1,2,3};
cout << a << endl; // 陣列名稱為陣列開始的位址
char c='x'; // 宣告字元
cout << c << endl;
cout << (int)c << endl; // ASCII
char s1[3]={'a','b','c'}; // 字元陣列,宣告長度為3的字串要多一個空間用來儲存空字元'\0'作為結束符號,否則會有錯誤
cout << s1 << endl;
char s1[4]={'a','b','c','\0'};
cout << s1 << endl;
string s2="abcd"; // 宣告string類別的字串
cout << s2 << endl;
cout << s2[1] << endl;
cout << s2.size() << endl;
```
### 2. 字串相關操作 [演算法筆記](https://archive.is/u1lQL)
:::info
EX_5_1:[b428: 凱薩加密](https://zerojudge.tw/ShowProblem?problemid=b428)
+ if 或 %
+ Q:可以寫b[1]-a[1]嗎?
:::
:::info
EX_5_2:[d235: Q10929:You can say 11](https://zerojudge.tw/ShowProblem?problemid=d235)
+ 11的倍數判別法:奇數位數字和與偶數位數字和相差為11的倍數。
+ 字串長度:n.size() 或 n.length()
+ 取絕對值函式:abs()
+ [1~13的倍數判別法](https://leestar2013.pixnet.net/blog/post/45638266)
:::
:::info
EX_5_3:[c276: 沒有手機的下課時間](https://zerojudge.tw/ShowProblem?problemid=c276)
:::
:::warning
[a009: 解碼器](https://zerojudge.tw/ShowProblem?problemid=a009)
:::
:::warning
[a065: 提款卡密碼](https://zerojudge.tw/ShowProblem?problemid=a065)
:::
:::warning
[d124: 3的倍数](https://zerojudge.tw/ShowProblem?problemid=d124)
+ 3的倍數判別法:各個數字和為3的倍數。
:::
:::warning
[a882: B. 我灰灰的橡皮鴨是個恐怖的危機](https://zerojudge.tw/ShowProblem?problemid=a882)
:::
:::warning
[b516: 凱撒密碼-商競103](https://zerojudge.tw/ShowProblem?problemid=b516)
:::
:::warning
[e505: 12602 - Nice Licence Plates](https://zerojudge.tw/ShowProblem?problemid=e505)
+ 取絕對值函式:abs()
:::
:::warning
[g006: 密碼備忘錄 (Password)](https://zerojudge.tw/ShowProblem?problemid=g006)
+ 以陣列儲存字母出現的次數(字母-'A'為索引值)。
+ 因為最多100個字母,表示次數最大為100,由100->1檢查陣列中是否有這個次數,如果有則輸出(char)(索引值+'A')
:::
## 六、函式(遞迴)
### 1. 自定函式宣告語法
``` c
回傳值的型態 函式名稱(變數型態 參數1,變數型態 參數2,...)
{
程式碼
return 回傳值或運算式;
}
```
:::info
EX_6_1:[a623: 3. Combination](https://zerojudge.tw/ShowProblem?problemid=a623)
+ 將n!寫成函式,在主程式呼叫3次。
+ $C(n,k)=\frac{n!}{(n-k)! * k!}$,例如C(4,2)=6。
:::
:::info
EX_6_2:[d237: 質數合](https://zerojudge.tw/ShowProblem?problemid=d237)
+ 以質數函式測試是否需加此數。
+ TLE如何解決
- long long sum=2;
for(int i=3;i<=2000000;i+=2)
- 如果一個數是合數,它的最小質因數會小於等於它的平方根。
- 因為成對出現的因數中,一個會 $\leq \sqrt n$,而另一個會 $\geq \sqrt n$。因此只要檢查 $\leq \sqrt n$ 中是否有 n 的因數即可。
- 開根號用sqrt(),需含入 cmath 標頭檔。
+ 不可直接輸出142913828922(超過int)。
:::
:::warning
[a121: 質數又來囉](https://zerojudge.tw/ShowProblem?problemid=a121)
+ 1不是質數。
:::
:::warning
[b112: 5. 高中運動會](https://zerojudge.tw/ShowProblem?problemid=b112)。
+ 寫一函式求兩數的最大公因數(輾轉相除法)。
:::
:::warning
[f327: 刪除欄位](https://zerojudge.tw/ShowProblem?problemid=f327)。
+ 寫一函式將輸入的字串轉成整數(26進位),A為1,B為2,…,AA為27,AA為28,…。
+ s[i]-'A'+1
:::
### 2. 傳值(call by value)、傳參考(call by reference)
:::info
EX_6_3:[d491: 我也愛偶數 (swap 版)](https://zerojudge.tw/ShowProblem?problemid=d491)
+ 將兩數交換寫成函式。
+ [等差數列](https://zh.wikipedia.org/wiki/%E7%AD%89%E5%B7%AE%E6%95%B0%E5%88%97)
+ ((b-a)/2+1)/2*(a+b) 會錯誤,分子可能是奇數。
:::
``` c=
void swap(int ~a, int ~b) // void 表示沒有回傳值
{
int t;
~
~
~
cout << "函式內:"<< a << " " << b << endl;
}
int main()
{
int a=1,b=2;
cout << "交換前:" << a << " " << b << endl;
swap(a,b);
cout << "交換後:" << a << " " << b << endl;
return 0;
}
```
### 3. 遞迴
:mega: 問題的答案,可從同類的子問題(規模更小)得到。
:mega: 在函式之中呼叫函式自己本身,要有終止條件,不然會無窮遞迴下去。
:::info
EX_6_4:[95數學學測填充題G](http://cs.cysh.cy.edu.tw/computer_concept_108/高中數學遞迴.pdf)
用黑、白兩種顏色的正方形地磚依照如下的規律拼成若干圖形:
![](https://i.imgur.com/PrDcedl.jpg)
拼第95個圖需用到幾塊白色地磚。(478)
:::
``` c=
int f(int n)
{
if ~ // if後只有一行,可省略{}
~
else
return ~
}
int main()
{
int n;
while(cin >> n)
cout << f(n) << endl; // 5->28
return 0;
}
```
:::info
EX_6_5:[a044: 空間切割](https://zerojudge.tw/ShowProblem?problemid=a044)
+ [直線分割平面](https://www.youtube.com/watch?v=wcvpvWxf-Kw)
- b~n~=b~n-1~+n,b~1~=2
+ [平面分割空間](https://www.youtube.com/watch?v=Fjd6Oz_cgYY)
- c~n~=c~n-1~+b~n-1~,c~1~=2
:::
:::warning
[a623: 3. Combination](https://zerojudge.tw/ShowProblem?problemid=a623)
+ 以遞迴改寫。
+ $C^n_k = C^{n-1}_k + C^{n-1}_{k-1}$
+ $n==k \ || \ k==0$ 時,只有一種組合方式。
:::
:::warning
[e357: 遞迴函數練習](https://zerojudge.tw/ShowProblem?problemid=e357)
:::
:::warning
[c002: 10696 - f91](https://zerojudge.tw/ShowProblem?problemid=c002)
:::
## 七、其它
### 1. [結構(struct)](https://kopu.chat/2017/05/30/c-%E8%AA%9E%E8%A8%80%EF%BC%9A%E7%B5%90%E6%A7%8B%EF%BC%88struct%EF%BC%89%E8%87%AA%E8%A8%82%E4%B8%8D%E5%90%8C%E8%B3%87%E6%96%99%E5%9E%8B%E6%85%8B%E7%B6%81%E4%B8%80%E8%B5%B7/)
``` c
// 自訂的資料型別
struct 結構名稱
{
資料型別 變數1;
資料型別 變數2;
...
};
```
:mega: struct 定義的最後面要加分號!
:::info
EX_7_1:[c316: 最遠點對!前傳](https://zerojudge.tw/ShowProblem?problemid=c316)
:::
:::warning
[a130: 12015 - Google is Feeling Lucky](https://zerojudge.tw/ShowProblem?problemid=a130)
:::
:::warning
[d809: 黑暗土地](https://zerojudge.tw/ShowProblem?problemid=d809)
+ [以行列式算三角形面積](http://euler.tn.edu.tw/area.pdf),避免浮點數誤差。
+ 取絕對值函式:abs()
+ 要印出面積時再/2.0。
:::