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 者必須先出牌,之後玩家輪
流出牌;出牌方式必須接續同花色且依照數字順序(往上由7至 K,往下由6至 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;
}
}
```
## 證書
