e575: 10908 - Largest Squares

  1. 1. 內容
  2. 2. 範例輸入
  3. 3. 範例輸出
  4. 4. 想法
  5. 5. 程式碼

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 演算法學習筆記

程式碼

C++
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;
}