CPE 一顆星選集 49 道必考題
題目連結:https://zerojudge.tw/ShowProblem?problemid=e575
內容
給定一個字元矩形及中心點座標,找出以此座標當中心所對應的最大正方形邊長。
輸入第一列 T (T < 21)代表測資數,每組測資第一列包含矩形高度 M,寬度 N(1 <= M, N <= 100),詢問數量 Q (Q < 21),接著有 Q 列中心點座標。
範例輸入
1
7 10 4
abbbaaaaaa
abbbaaaaaa
abbbaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaccaaaaaa
aaccaaaaaa
1 2
2 4
4 6
5 2
範例輸出
7 10 4
3
1
5
1
想法
將矩形內每一點都視為正方形的右下角座標,發現以該點為右下角座標所構成的最大正方形邊長,取決於其左、上、左上這三點構成之正方形最大邊長的最小值 + 1,即可建一個陣列儲存。
因輸入為中心點座標,而陣列儲存數值為右下角,因此需不斷向陣列右下角查詢,直到其值無法再更大。
參考資料:YUI HUANG 演算法學習筆記
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <bits/stdc++.h> #define fastio ios_base::sync_with_stdio(false), cin.tie(nullptr) using namespace std;
int main(){ fastio; int T, m, n, q, dp[101][101]; char mp[101][101]; cin >> T; while(T--){ cin >> m >> n >> q; for(int i = 0; i < m; ++i){ for(int j = 0; j < n; ++j){ cin >> mp[i][j]; } } for(int i = 0; i < m; ++i){ for(int j = 0; j < n; ++j){ if(i == 0 || j == 0) dp[i][j] = 1; else if(mp[i][j] == mp[i-1][j-1] && mp[i][j] == mp[i-1][j] && mp[i][j] == mp[i][j-1]){ dp[i][j] = min({dp[i-1][j-1], dp[i-1][j], dp[i][j-1]}) + 1; } else dp[i][j] = 1; } } int y, x, ans; cout << m << " " << n << " " << q << "\n"; while(q--){ cin >> y >> x; ans = 1; ++y, ++x; while(y < m && x < n){ if(dp[y][x] >= ans+2){ ans += 2; ++y, ++x; } else break; } cout << ans << "\n"; } } return 0; }
|