# 二維陣列
###### 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
```
---
## 二維陣列
----
大家應該能想像的到二維陣列是什麼東西了:
就好像數學的「平面座標」一樣 !

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}]"}