此筆記為APCS 2023年10月實作題考試的題目詳解。每一題的題解都包含解題思路、C++範例程式碼。
有
老鼠在開始覓食前要選擇今天要往左邊或往右移動去尋找食物,經過食物時可以停下來吃食物,吃完後可以選擇繼續往相同方向移動,或者是結束今天的覓食。
請問老鼠最多能吃到多少個食物,以及最後停下來吃食物的位置。
輸入說明 | 輸出說明 |
---|---|
![]() |
![]() |
我利用 ti 儲存左邊的食物量、tx 儲存右邊的食物量,而 min 儲存最左邊的食物所在位置、max 儲存最右邊的食物所在位置。
當輸入值
最後判斷 ti 與 tx 的大小,取大的輸出,並同時輸出 min 或 max 為最後停下的位置。
#include <iostream>
using namespace std;
int main()
{
int i;
int x, n, a, min, max = 0, ti = 0, tx = 0;
cin >> x >> n;
min = x;
for (i=0;i<n;i++) {
cin >> a;
if (a < x) {
if (a < min)
min = a;
ti++;
}
else {
if (a > max)
max = a;
tx++;
}
}
if (tx > ti)
cout << tx << " " << max;
else
cout << ti << " " << min;
return 0;
}
AC (2ms, 320KB)
你有一個
每一種數字在表格中出現恰好兩次。消除兩個相同的數字
消除規則:你可以垂直或水平地將兩個相同數值的元素消除,但消除的兩個元素之間不能有其他尚未消除的元素。
輸入說明 | 輸出說明 |
---|---|
![]() |
![]() |
這題可以直接暴力解出來,不斷移除相同的數字並增加得分即可。當遍歷一遍表格後得分並未增加,則視為終止。
題目宣稱每一種數字出現恰好 2 次,所以上下、左右各只需要選擇一個方向即可(我選擇下、右)。
#include <iostream>
using namespace std;
int main ()
{
int i, j, k;
int n, m, point = 0;
int ok = 1;
cin >> n >> m;
int x[n][m];
for (i=0;i<n;i++)
for (j=0;j<m;j++)
cin >> x[i][j];
while (ok == 1) {
ok = 0;
for (i=0;i<n;i++) {
for (j=0;j<m;j++) {
if (x[i][j] != -1) {
for (k=i+1;k<n;k++) {
if (x[k][j] == x[i][j] && x[i][j] != -1) {
ok = 1;
point = point + x[i][j];
x[k][j] = -1;
x[i][j] = -1;
break;
}
if (x[k][j] != -1)
break;
}
for (k=j+1;k<m;k++) {
if (x[i][k] == x[i][j] && x[i][j] != -1) {
ok = 1;
point = point + x[i][j];
x[i][k] = -1;
x[i][j] = -1;
break;
}
if (x[i][k] != -1)
break;
}
}
}
}
}
cout << point;
return 0;
}
AC (3ms, 332KB)
忍者龜住在下水道中,他們正在準備搬家。下水道由
其中,X 代表十字架,而 H、I、F、7、L 分別代表其他不同形狀的水管。0 字元代表沒有水管連接的地方。
請注意,在某個連通塊內的水管可以連接,而不同連通塊的水管不會相互連接。
下面是一些可能的水管形狀:
水管的開口方向與字元對應關係
F: 右和下
H: 左和右
7: 左和下
I: 上和下
X: 上、下、左和右
L: 右和上
J: 左和上
0: 沒有水管
輸入說明 | 輸出說明 |
---|---|
![]() |
![]() |
這題我使用 dfs 解的時候,由於記憶體不夠,因此會卡在 95%,最終利用 bfs 即得到 AC 解。
由於我習慣用 queue 處理 bfs 排序,因此我透過一個簡單的換算方式,將二維陣列轉為一維陣列的形式。將 tunnel[i][j] 換算為 tunnel[
我會先讀入資料,當讀到沒走過的水管後,開始一個新的 bfs。我利用 pipe 陣列儲存已走過的資料,以確保 bfs 的都是新的水管(不必重複讀取已走過的水管),並透過 now 儲存該連通塊的水管數量,並與 Max 比較大小,最終 Max 即為本題解答。
#include <bits/stdc++.h>
using namespace std;
bool up (char ch)
{
return ch == 'I' || ch == 'L' || ch == 'J' || ch == 'X';
}
bool down (char ch)
{
return ch == 'I' || ch == '7' || ch == 'F' || ch == 'X';
}
bool left (char ch)
{
return ch == 'H' || ch == 'J' || ch == '7' || ch == 'X';
}
bool right (char ch)
{
return ch == 'H' || ch == 'L' || ch == 'F' || ch == 'X';
}
int main ()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i, j, k;
int n, m, a, x;
int Max = 0, now;
cin >> n >> m;
char tunnel[(n+2)*(m+2)];
int pipe[(n+2)*(m+2)]={};
memset(tunnel, '0', sizeof(tunnel));
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
cin >> tunnel[(i-1)*m+j];
for (i=1;i<=n;i++) {
for (j=1;j<=m;j++) {
a = (i - 1) * m + j;
if (pipe[a] == 0 && tunnel[a] != '0') {
pipe[a] = 1;
now = 0;
queue <int> run;
run.push(a);
while (run.size() != 0) {
x = run.front();
now++;
if (up(tunnel[x]) && down(tunnel[x-m]) && pipe[x-m] == 0) {
pipe[x-m] = 1;
run.push(x-m);
}
if (down(tunnel[x]) && up(tunnel[x+m]) && pipe[x+m] == 0) {
pipe[x+m] = 1;
run.push(x+m);
}
if (left(tunnel[x]) && right(tunnel[x-1]) && pipe[x-1] == 0) {
pipe[x-1] = 1;
run.push(x-1);
}
if (right(tunnel[x]) && left(tunnel[x+1]) && pipe[x+1] == 0) {
pipe[x+1] = 1;
run.push(x+1);
}
run.pop();
}
if (now > Max)
Max = now;
}
}
}
cout << Max;
return 0;
}
AC (27ms, 1.5MB)
你擁有一個長度為
你可以自行決定投資的開始和結束日期。在你選擇投資的每一天,你可以選擇消耗一張金牌來跳過當天,或者不使用金牌而拿取當天的收益。你的目標是找出如何投資,以實現最大的總收益。
請注意,你只能在投資期間進出一次。
輸入說明 | 輸出說明 |
---|---|
![]() |
![]() |
這題是 dp 題,與背包問題類似。
我利用 dp[i][j] 儲存 i 個金牌、第 j 天的收益。需要注意的是,dp 時我利用 j 代表金牌數,因此在第 21 行使用 dp[j][i]。
根據題目可歸納出,dp[i][j] 就是不斷比較 i 個金牌、第 j 天的收益(該日不使用金牌的收益)與 i - 1 個金牌、第 j - 1 天的收益(該日使用金牌後的收益),而最終答案就是 dp[k+1][i](1 ≤ i ≤ n)時的最大值(我另 k + 1 作為 k 個獎牌的情形)。
#include <iostream>
using namespace std;
int a[1000000];
int dp[50][1000000]={};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i, j;
int n, k, b, max;
cin >> n >> k;
for (i=1;i<=n;i++) {
cin >> a[i];
for (j=1;j<=k+1;j++) {
dp[j][i] = dp[j-1][i-1];
b = dp[j][i-1] + a[i];
if (dp[j][i] < b)
dp[j][i] = b;
}
}
max = dp[k+1][0];
for (i=1;i<=n;i++) {
if (dp[k+1][i] > max)
max = dp[k+1][i];
}
cout << max;
}
AC (25ms, 9.3MB)
APCS實作題
查看更多資訊請至:https://www.tseng-school.com/