---
# System prepended metadata

title: 2023_11_ITSA心得

---

2023 11 ITSA
===

## 前言
這是我第一次參加ITSA,前幾題難易度適中,只有第三題沒看懂題意,卡比較久,其他題都沒花太多時間，整體考試時間3個小時也算充裕,不過賽前要記得先測試考試用的PS2,下面整理了這次前五題的題解


## Problem 1. 字元計算
### 題目
問題描述:
現在有多個字元，請寫一個程式，根據輸入的字元，統計 a-z 各字元出現次數。

輸入說明
第一行有 1 個正整數 N（1 ≤ N ≤ 1,000），表示共有幾個字元，接著會有 N 行，每
行為一小寫字元 (a-z)。

輸出說明:
根據輸入的字元，根據字元的排序 (a-z) 顯示各字元的出現次數，如果字元次數為 0
次則不須顯示，最後會有換行。
### 解題思路
- 用字串`s`存a-z
- 每一筆輸入對照字母後用陣列`d`紀錄字母出現次數
```cpp==
#include <iostream>
using namespace std;
int main() {
    int n,k,i,t=0,d[26];
    cin>>n;
    char j;
    string s="abcdefghijklmnopqrstuvwxyz";
    for(i=0;i<26;i++)   d[i]=0;
    for(i=0;i<n;i++)
    {
        cin>>j;
        k=j-'a';    //把字元轉成ascii code再到陣列儲存
        d[k]++;
    }
    for(i=0;i<26;i++)
    {
        if(d[i]!=0)
        {
            cout<<s[i]<<' '<<d[i]<<endl;
        }
    }
}
```
## Problem 2. 漏水
### 題目
問題描述:
小和尚想到山下挑水上來裝滿蓄水池，但蓄水池被老鼠咬了一個小洞，小和尚不知情
的依舊維持他今日的挑水工作，假設小和尚每次可以挑 R 單位的水上來，但是在小和尚再次
下山到上山的時間，蓄水池會漏出 D 單位的水，請問小和尚要花多久才能裝滿蓄水池。
(下山挑水加上山為 1 小時) 。

輸入說明
每組測試資料 3 行，
第一行有 1 個浮點數 N（0 < N < 10,000），代表蓄水池的滿水單位。
第二行有 1 個浮點數 R（0 < R < N < 1,000），代表小和尚每次可填入的水量。
第三行有 1 個浮點數 D（0 < D < R），代表小和尚再次下山到上山時，蓄水池漏出的水單位。

輸出說明:
計算小和尚要花多久才能裝滿蓄水池，最後會有換行。
### 解題思路
- 輸入有小數點,所以要用`float`存
- 用`while`迴圈計算要多久會滿水
```cpp=
#include <iostream>
using namespace std;
int main() {
    float a,b,c,d=0,t=0,i;
    cin>>a>>b>>c;
    while(1)
    {
        d+=b;    //紀錄水池水量
        if(d>a)    //檢查是否滿水
        {
            cout<<t;
            break;
        }
        d-=c;    //減掉流走的水
        t++;    //計算次數
    }
}
```
## Problem 3. 排 7
### 題目
問題描述:
排 7 是一個多人的撲克牌遊戲，其規則為，玩家擁有♥7 者必須先出牌，之後玩家輪
流出牌；出牌方式必須接續同花色且依照數字順序（往上由７至 K，往下由６至 A），或者
發出其他花色的 7，直到所有人用完手牌為止。舉例而言，有人出♥7，下一位玩家必須發出
♥6 或♥8，也可發出♠7、♣7 或♦7；當有人沒辦法出牌時，必須選擇從手上覆蓋一張牌來略
過這次出牌機會，此牌到遊戲結束前不可明示。遊戲結束時計算覆蓋牌點數的總和，最多的
人最輸，但是從頭到尾都覆蓋牌的人算最贏。
請寫一個程式，根據手上的牌，以及牌桌上已經出過的牌，判斷目前自己手上有哪些
牌可以出。

輸入說明:
第一行有 1 個正整數 N（1 ≤ N ≤ 20），表示牌桌上已經出過的撲克牌數量，第二行
會有 N 個正整數 P（0 ≤ P ≤ 52），每個整數中間用 1 空格隔開，每個正整數都表示 1 張
牌，每個整數中間用 1 空格隔開，如下所示：
梅花♣ : 1~13 =數字 0~12
方塊♦ : 1~13 =數字 13~25
紅心♥ : 1~13 =數字 26~38
黑桃♠ : 1~13 =數字 39~51
第三行有 1 個正整數 H（1 ≤ N ≤ 20），表示手上牌的數量，第四行會有 H 個正整
數，表示手上的每張牌，每個整數中間用 1 空格隔開，
例如，目前已經出過的牌為♣7 ♦7 ♥7 ♠7 手上牌為♣1 ♦2 ♦6 ♦12 ♥11 ♠4 ♠8，則
為：
4
6 19 32 45
7
0 14 18 24 36 42 46

輸出說明:
輸出目前自己手上可以出牌的數量。
最後會有換行。
### 解題思路
- 陣列`d`紀錄桌上已出過的牌
- 陣列`r`記錄手牌
- 一個`if`判斷是否可以接牌
- 另一個判斷是否可出其他花色的7
```cpp=
#include <iostream>
#include <utility>
using namespace std;
int main() {
    int a,b,c,t=0,i,j;
    string s;
    cin>>a;
    int d[a];
    for(i=0;i<a;i++)
    {
        cin>>d[i];
    }
    cin>>b;
    int r[b];
    for(i=0;i<b;i++)
    {
        cin>>r[i];
        for(j=0;j<a;j++)
        {
            if(r[i]==d[j]+1||r[i]==d[j]-1)  t++;    //判斷牌是否可接在前後
            if(d[j]==6||d[j]==19||d[j]==32||d[j]==45)    
            {
                if(r[i]==d[j]+13||r[i]==d[j]-13)    //判斷能不能出其他花色的7
                {
                    t++;
                }
            }
        }
    }
    cout<<t;

}
```
## Problem 4. 會員資料查詢
### 題目

問題描述:
現在有會員資料如下：


| 會員編號  | 姓名      | 類別      |
| -------- | -------- | -------- |
| 123      | Tom      | DTGD     |
| 456      | Cat      | CSIE     |
| 789      | Nana     | ASIE     |
| 321      | Lim      | Dba      |
| 654      | Won      | FDD      |

請您寫一系統，可輸入關鍵字與指定搜尋的項目，可以撈出會員的資料。
※搜尋方式採精準搜尋：關鍵字必須與要搜尋的資料完全一樣。(不分大小寫)

輸入說明
第一行有 1 個正整數 N（1 ≤ N ≤ 10），代表有 N 個指令，接著會有 N 行，每一行
有兩個參數，第 1 個參數代表要指定搜尋的項目，其中 1 表示要查詢會員編號、2 表示姓
名、3 表示類別；第二個參數代表要搜尋的關鍵字。

輸出說明:
把找到的那個會員依序印出他的會員編號、姓名、類別，兩兩間有 1 個空白隔開。
最後會有換行。

### 解題思路
- 這題只有五個資料,所以我直接用五個if判斷並輸出
```cpp=
#include <iostream>
using namespace std;
int main() {
    int a,b,c,t=0,i;
    string s;
    cin>>a;
    for(i=0;i<a;i++)
    {
        cin>>b;
        if(b==1)
        {
            cin>>c;
            if(c==123)
            {
                cout<<"123 Tom DTGD"<<endl;
            }
            else if(c==456)
            {
                cout<<"456 Cat CSIE"<<endl;
            }
            else if(c==789)
            {
                cout<<"789 Nana ASIE"<<endl;
            }
            else if(c==321)
            {
                cout<<"321 Lim DBA"<<endl;
            }
            else
            {
                cout<<"654 Won FDD"<<endl;
            }
        }
        else if(b==2)
        {
            cin>>s;
            if(s[0]=='T'||s[0]=='t')
            {
                cout<<"123 Tom DTGD"<<endl;
            }
            else if(s[0]=='C'||s[0]=='c')
            {
                cout<<"456 Cat CSIE"<<endl;
            }
            else if(s[0]=='N'||s[0]=='n')
            {
                cout<<"789 Nana ASIE"<<endl;
            }
            else if(s[0]=='L'||s[0]=='l')
            {
                cout<<"321 Lim DBA"<<endl;
            }
            else
            {
                cout<<"654 Won FDD"<<endl;
            }
            
        }
        else
        {
            cin>>s;
            if(s[0]=='D'&s.length()==4||s[0]=='d'&s.length()==4)
            {
                cout<<"123 Tom DTGD"<<endl;
            }
            else if(s[0]=='C'||s[0]=='c')
            {
                cout<<"456 Cat CSIE"<<endl;
            }
            else if(s[0]=='A'||s[0]=='a')
            {
                cout<<"789 Nana ASIE"<<endl;
            }
            else if(s[0]=='D'||s[0]=='d')
            {
                cout<<"321 Lim DBA"<<endl;
            }
            else
            {
                cout<<"654 Won FDD"<<endl;
            }
        }
    }
}
```
## Problem 5. 村莊距離普查
### 題目
問題描述:
村長現在想要統計村子裡面每條路的距離，每個人家到另外一個人家中間可能會有一
條路，村長想要知道這些路誰家到誰家較近，方便做一個緊急通訊錄，以防不時之需。 

輸入說明
第一列的整數 ( 1 < n < 20 ) ，代表村中的道路共有幾條，其後有 n 列，每一列有
三個整數 x,y,d 代表的分別是村中某戶人家 x 到另一戶人家 y 的道路距離是 d ，其中距
離的值不超過 2000 ，且沒有數值相同的距離，各項資料用空白分開。

輸出說明:
印出排序後的道路距離由小到大 ，最後必須有換行字元。
### 解題思路
- 開一個二維陣列`l`存`x`,`y`,`d`;
- 用Bubble sort比路徑長短
```cpp=
#include <iostream>
#include <utility>
using namespace std;
int main() {
    int a,b,c,t=0,i;
    string s;
    cin>>a;
    int l[a][3];
    for(i=0;i<a;i++)
    {
        cin>>l[i][0]>>l[i][1]>>l[i][2];
    }
    while(t>=0)
    {
        for(i=0;i<a-1;i++)
        {
            if(l[i][2]>l[i+1][2])
            {
                //一次交換三個值
                swap(l[i][0],l[i+1][0]);
                swap(l[i][1],l[i+1][1]);
                swap(l[i][2],l[i+1][2]);
                t++;
            }
        }
        t--;
    }
    for(i=0;i<a;i++)
    {
        cout<<l[i][0]<<' '<<l[i][1]<<' '<<l[i][2]<<endl;
    }
}
```
## 證書
![image](https://hackmd.io/_uploads/HJ3aPvVwT.png)