# 二維陣列 ###### tags: `MDCPP講義` --- ## 模擬賽回顧: 1. 一元二次方程求解 ( 10 / 17 ) 2. 總是迷路的極速車神大佬 ( 0 / 17 ) 3. 我要成為新進股神 ( 4 / 17 ) 4. 尋找中位數 ( 8 / 17 ) 5. 爬山好累 ( 0 / 17 ) ---- 來看看詳解:https://hackmd.io/@gary940610/r1hshwWH9 ! --- ### 讓我們先來複習一下陣列、字串 ---- ```cpp= int arr[10]; // 長度為10的 int 陣列 ``` ---- ```cpp= arr[5] = 3; cout << arr[5]; // 3 cin >> arr[5]; // 如果是 5 cout << arr[5]; // 5 ``` ---- ```cpp= string str; cin >> str; // 如果是 hello cout << str; // hello cout << str[3]; // l ``` --- ## 二維陣列 ---- 大家應該能想像的到二維陣列是什麼東西了: 就好像數學的「平面座標」一樣 ! ![](https://i.imgur.com/yw4h5Yt.png) From https://ithelp.ithome.com.tw/m/articles/10215056 ---- #### 如此一來,他能讓我們儲存更多類型的資料 ---- ### 宣告方式: ---- 可能有人會想用這種方式: ```cpp= int arr1[10]; // 第一橫列有10個數字 int arr2[10]; // 第二橫列有10個數字 int arr3[10]; . int arr4[10]; . . . . int arr10[10]; ``` 但很明顯的,這樣很麻煩,而且不好用 ---- ### 宣告方法 ```cpp= int arr1[3][3]; // 宣告一個二維陣列 ( 不保證裡面的數字 ) int arr2[3][3] = {}; // 宣告一個空的二維陣列 int arr3[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; /* arr3 長這樣 1 2 3 4 5 6 7 8 9 */ ``` ---- ### 讀取、修改方法 ```cpp= // 輸入、輸出 cin >> arr[2][5]; // 將第5橫列,第二直行的 int 輸入 // ( 假設輸入 4) cout << arr[2][5]; // 4 arr[2][5] = 10; cout << arr[2][5]; // 10 ``` ---- ### 遍歷整個二維陣列 這時候就要搭配雙層迴圈了 ! 通常,我們會以兩個變數分別控制「第幾列」和「第幾列」: ```cpp= int mat[5][5] = {}; for(int i = 0; i < 5; i++) { for(int j = 0; j < 5; j++) { cout << mat[i][j] << ' '; } cout << endl; } // i 代表第幾列,j 代表第幾行 ``` ---- 結果如下: ``` 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ``` ---- ### 這一定很難想像,所以我準備了這個: https://replit.com/@gary940610/Er-Wei-Zhen-Lie-Lian-Xi#main.cpp 大家來練習跑跑看這個,相信能更容易了解二維陣列 ! 也可以試著下載、複製下來,改改看 ! ---- ### 重點: :::info 因為程式輸出為一行一行的關係,所以我們在程式常用的座標跟(x, y)座標是相反的 ! 例如: ::: ``` . O . . . . . . . 一般座標:(2, 1) 程式座標:(1, 2) ``` [a][b] 目前位置 [a][b + 1] 右邊一格 [a + 1][b] 下面一格 [a - 1][b] 上面一格 [a][b - 1] 左邊一格 ---- ### 二維陣列的位置關係: 另一個小程式: 這個程式能更有幫助地了解如何陣列位置的相對關係 ! https://replit.com/@gary940610/Er-Wei-Zhen-Lie-Xiang-Dui-Wei-Zhi-Lian-Xi#main.cpp --- ## 應用 ---- #### 暖身: [簡單運算LV1](http://mdcpp.mingdao.edu.tw/problem/A029) 給定一個3x3的陣列,將第二行的數字加上第一行的數字,第三行的數字加上第二行的數字。 舉例來說 1 2 3 > 1 2 3 > 1 2 3 4 5 6 > 5 7 9 > 5 7 9 7 8 9 > 7 8 9 > 12 15 18 ---- 解題關鍵: 可以發現,我們一定要先跑完每一行的數字,才能往下一行跑 => 那我們可以設一個 i 代表到第幾行,j 代表到第幾列 ! ```cpp= // ( 主程式碼 ) for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { mat[i][j] = mat[i - 1][j] + mat[i][j]; } } ``` ---- #### 中等: [矩陣翻轉](http://mdcpp.mingdao.edu.tw/problem/A032) 給你一個矩陣,請你把行與列調換 這是某年 APCS 的第二題,也是一題經典題 ! 這題需要你好好思考,才能想出正確地解法喔 ! ---- ```txt input 2 3 3 1 2 8 5 4 ``` ```txt output 3 8 1 5 2 4 ``` ```cpp= #include <iostream> using namespace std; int num[10][10]; int main() { int n, m; cin >> n >> m; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { cin >> num[i][j]; } for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) cout << num[j][i] << ' '; cout << endl; } } ``` ---- #### 困難: [文化炸彈](http://mdcpp.mingdao.edu.tw/contest/29/problem/T16) 現在有一個 $N \times M$ 的城市,幫每次爆破一個城市的時候,附近的九宮格也會跟著炸毀。 每個城市都有它自己的價值,給定爆破位置,請問每次爆破後,所能爆破的城市價值總和是多少 ? ( 爆破後的城市再爆破不會有效 ) ---- 這題就要用到我們剛剛講到的觀念了 -- 二維陣列的相對位置 一個格子的九宮格其實就是以下的排列組合: ``` [a - 1] [b - 1] [a] × [b] [a + 1] [b + 1] ``` ---- 那我們每次有一個爆破位置 $a, b$ 的時候,我們只要讀取上面的幾個排列出來的位置,並加總起來就可以了 ! 而對於爆破之後不列入計算的部分,也就是可以把這些位置的值改變成 0,之後 +0 也沒有關係,這就是我們要的數值。 ---- ```cpp= #include<bits/stdc++.h> using namespace std; int arr[1050][1050]; signed main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { cin >> arr[i][j]; } int q; cin >> q; int ans = 0; for (int i = 1; i <= q; i++) { int a, b; cin >> a >> b; for (int j = a - 1; j <= a + 1; j++) for (int k = b - 1; k <= b + 1; k++) { if (j >= 1 && k >= 1) { if (arr[j][k] != 0) ans += arr[j][k], arr[j][k] = 0; } } } cout << ans << endl; } ``` --- ## 多維陣列 ---- 陣列有一維、二維,那有沒有三維四維... ? 答案是肯定的 ! 事實上,陣列要有多少維都可以,只要記憶體負荷得了, 讀取速度也會較慢一些 ! ---- 當然,三維四維的陣列不太會需要印出來,因為你也印不出來。 ( 有人能告訴我什麼是四維空間嗎 ) 但我們偶爾還是會用到三維、四維的陣列,而基本上五維以上不會用到。 ---- 宣告方法大概也知道了吧 ! ```cpp= int arr1[10][10][10]; int arr2[10][10][10] = {}; int arr3[2][2][2] = { { {1, 2}, {3, 4} }, { {5, 6}, {7, 8} } } int arr4[10][10][10][10]; ``` ---- 輸入、輸出方法 ```cpp= cout << arr1[5][6]; cout << arr4[5][6][7][8]; ``` ---- ### 多維陣列應用 多維陣列的應用通常較為複雜,這裡先給一個簡單的例子: 給你一個座標從 (0, 0, 0) 到 (9, 9, 9) 的立方體,每個整數座標點的價值為 長 + 寬 + 高 給你一個三維的點,請問以他為中心,邊長為二的立方體所包括的價值總和為多少 ? 這題就留給大家思考 ( 因為用到了一些高中數學觀念,在此就先不提 ) ---- ## 例題 http://mdcpp.mingdao.edu.tw/problem/A029 http://mdcpp.mingdao.edu.tw/problem/A032 http://mdcpp.mingdao.edu.tw/contest/29/problem/T16 http://mdcpp.mingdao.edu.tw/contest/29/problems/T17 http://mdcpp.mingdao.edu.tw/contest/29/problems/T18 [矩陣翻轉變化題](https://zerojudge.tw/ShowProblem?problemid=b266) https://zerojudge.tw/ShowProblem?problemid=g596 ---- ## 謝謝大家
{"metaMigratedAt":"2023-06-17T00:56:47.639Z","metaMigratedFrom":"Content","title":"二維陣列","breaks":true,"description":"一元二次方程求解 ( 10 / 17 )","contributors":"[{\"id\":\"6a375517-4167-4b7c-a983-1e595a29262c\",\"add\":5918,\"del\":904}]"}
    664 views
   owned this note