開啟章節選單
矩陣總和
解題想法
1. 設立二維陣列
題目敘述中提到, 分別為矩陣 和矩陣 的長寬,因此可以依照題意,創建以下變數:
int s, t, n, m, r, total = 0, ans = INT_MAX, asum = 0; int a[15][105], b[15][105];
以上除了題目提到的正整數外,還有 total
, ans
, asum
這三個變數,分別計算子矩陣總和、相差最小值和矩陣 總和。
注意
根據題目敘述,我們要得出符合條件的子矩陣數和與矩陣 相差最小的值,因此變數 ans
要設定為無限大,也就是這裡使用的 INT_MAX
,代表 int
的最大值。
2. 輸入矩陣
在輸入矩陣時,我們可以在同時計算矩陣 的總和,如下:
for (int i = 1; i <= s; i++) { for (int j = 1; j <= t; j++) { cin >> a[i][j]; asum += a[i][j]; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> b[i][j]; } }
3. 檢查所有子矩陣 ( 枚舉 )
在題目敘述中,需要我們檢查所有可能的子矩陣,也就是大小跟矩陣 一樣,但不超過矩陣 的範圍。
我們在前面章節中提到,如果我們呼叫超出範圍的陣列元素時,會得到記憶體區位段錯誤,所以我們可以用以下程式,確保我們不會取到不適合的索引值,如下:
for (int i = 1; i <= n - s + 1; i++){ for (int j = 1; j <= m - t + 1; j++){ //... } }
以上為一個雙層迴圈,其中只會跑 的範圍,確保我們不會輸入不正確的索引值。
之後就是枚舉所有子矩陣,並且算出兩矩陣的元素不相同數,從而判斷是否符合題目要求,即元素不相同數不超過 :
int tmp = 0; int diff = 0; for (int x = 1; x <= s; x++) { for (int y = 1; y <= t; y++) { diff += (b[i + x - 1][j + y - 1] != a[x][y] ? 1 : 0); tmp += b[i + x - 1][j + y - 1]; } }
如果符合要求,我們就會計算兩矩陣相差值,並且比較是否為新的最小值:
if (diff <= r) { total++; ans = min(abs(tmp - asum), ans); }
4. 輸出答案
本題有一個小細節,就是當沒有子矩陣符合條件時,第二行要輸出 ,因此在程式的最後可以增加其三元判斷式:
cout << total << '\n' << (ans == INT_MAX ? -1 : ans) << '\n';
以上式子會判斷變數 ans
是否被改值,如果沒有,就輸出 ,否則輸出 ans
。
範例程式
#include <bits/stdc++.h> using namespace std; int s, t, n, m, r, total = 0, ans = INT_MAX, asum = 0; int a[15][105], b[15][105]; int main() { cin >> s >> t >> n >> m >> r; for (int i = 1; i <= s; i++) { for (int j = 1; j <= t; j++) { cin >> a[i][j]; asum += a[i][j]; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> b[i][j]; } } for (int i = 1; i <= n - s + 1; i++) { for (int j = 1; j <= m - t + 1; j++) { int tmp = 0; int diff = 0; for (int x = 1; x <= s; x++) { for (int y = 1; y <= t; y++) { diff += (b[i + x - 1][j + y - 1] != a[x][y] ? 1 : 0); tmp += b[i + x - 1][j + y - 1]; } } if (diff <= r) { total++; ans = min(abs(tmp - asum), ans); } } } cout << total << '\n' << (ans == INT_MAX ? -1 : ans) << '\n'; return 0; }