# APCS 2024/6月題解 ::: success ## 1. 特技表演 ::: ### 敘述: 一個城鎮有n棟高樓,樓高為h1,h2,...,hn。 城鎮中心將舉辦高空特技表演,該特技表演會從某棟大樓上朝右側滑翔至地面。 為了表演人員的安全,滑翔的路徑樓高必須越來越低,請找出一個最長的滑翔路徑。 **5<=n<=100, 1<=hi<=1000** ### 核心: <font color="#F7A004">**迴圈、條件判斷**</font> ### 思路: 腦海中浮現第一個想法是用陣列存取後跑一次迴圈,找<font color="#4678C1">最長遞減序列</font>。這想法肯定沒錯,但還能更快。 利用兩變數<font color="#4678C1">**last,now**</font>當上一個樓高和目前樓高,直接在輸入迴圈中做運算。 如果now小於last,長度length++並更新最大值ans,else重新計算長度。 <font color="#f00">(注意!!若選擇在else中更新ans,最後於答案輸出前還需再更新一次ans值。)</font> ``` #include<bits/stdc++.h> using namespace std; #define oo 1005 int main() { int n; int last=oo,now; int ans=0,length=0; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d", &now); if(now<last) length++,last=now,ans=max(ans,length); else length=1,last=now; } printf("%d\n",ans); } ``` ::: success ## 2. 電子畫布 ::: ### 敘述: 有一個H*W的電子畫布,一開始數值都是0代表未填色,接下來請模擬N次畫筆操作。 每次操作為選一個座標(r,c),他會將曼哈頓距離<=t的區塊染上顏色x。 若有多個顏色重複填到相同區塊,顏色的數值會累加起來。 請輸出N次操作後的畫布狀態。 **1<=H,W<=20, 1<=N<=100** ### 核心: <font color="#F7A004">**模擬、二維陣列**</font> ### 思路: 模擬題,沒什麼好說的,模擬N次操作,用矩形範圍去判斷是否滿足曼哈頓距離。 ``` #include<bits/stdc++.h> using namespace std; #define M 105 int main() { int H,W,N; int paper[M][M]={0}; scanf("%d%d%d",&H,&W,&N); int r,c,t,x; for(int n=0; n<N; n++) { scanf("%d%d%d%d",&r,&c,&t,&x); for (int i=max(0, r-t); i<min(H,r+t+1); i++) { for (int j=max(0,c-t); j<min(W,c+t+1); j++) { if (abs(r-i)+abs(c-j) <= t) paper[i][j]+=x; } } } for(int i=0; i<H; i++) { for(int j=0; j<W; j++) printf("%d ",paper[i][j]); printf("\n"); } } ``` ::: success ## 3. 缺字問題 ::: ### 敘述: 給定一個大小為K個字母的集合和字串S,求出在使用該集合所組出長度為L字串中,不為字串子字串的最小字典序字串為何。 ### 核心: <font color="#F7A004">**DFS枚舉、string處理、Sliding Window"**</font> ### 思路: 直接枚舉就對了,由於已經按字典序作枚舉,當找到的第一個不在set str中的字串即為答案。 **1<=K<=10, 1<=L<=8, 1<=|s|<=5*10^5** 此題參考APCS Guide寫法進行優化 ``` #include <bits/stdc++.h> using namespace std; string K,S,ans; int L; set<string> str; void dfs(int idx) { if (idx==L) { if (str.count(ans)) return; cout<<ans<<endl; exit(0); } for (int i=0; i<K.size();i++) { ans[idx]=K[i]; dfs(idx+1); } } signed main() { cin>>K>>L>>S; ans=string(L,K[0]); for (int i=0;i<=S.size()-L;i++) str.insert(S.substr(i,L)); dfs(0); } ``` ::: success ## 4. 最佳選擇 ::: ### 敘述: 給一個長度為n的正整數序列a1,a2,...,an。 可以執行多次操作(包含0次),每次操作只能選擇這個序列的第一個或最後一個數字,再將這個數字從序列中刪除並自己搜集起來。 求滿足總和不超過K且搜集的數字奇數和偶數個數相同的條件下,所能搜集的數字總和最大為多少。 ### 直接看大佬解法: [APCS Guide解](https://hackmd.io/@04vUD_k9QzqIoVtFM5Bm_g/apcs202406#%E5%9B%9B%E3%80%81%E6%9C%80%E4%BD%B3%E9%81%B8%E6%93%87)