반응형
행렬은 알고리즘 문제를 풀 때도 그렇고, 3D 코딩을 할때도 필요하고 여러모로 쓸 경우가 많은것 같아 여기 정리합니다.
먼저 나이브한 행렬곱셈을 구현해보면 다음과 같습니다. (관련 문제: 백준 2740번 행렬곱셈)
|
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
|
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll A[101][101], B[101][101], C[101][101];
int main(void)
{
int n, m; scanf("%d %d", &n, &m);
for (int y = 0; y < n; y++)
for (int x = 0; x < m; x++)
scanf("%lld", &A[y][x]);
int k; scanf("%d %d", &m, &k);
for (int y = 0; y < m; y++)
for (int x = 0; x < k; x++)
scanf("%lld", &B[y][x]);
for (int y = 0; y < n; y++) {
for (int x = 0; x < k; x++) {
for (int i = 0; i < m; i++)
C[y][x] += A[y][i] * B[i][x];
printf("%lld ", C[y][x]);
}
printf("\n");
}
return 0;
}
|
cs |
특별할건 없고, 2차원 배열로 잡고 y, x (또는 행, 열 이라고도 표현 가능) 순으로 인덱스 할당해서 계산한다는 것..
근데 한가지 불편한점이 발견되는것은 곱셈결과를 리턴하도록 함수로 뺄 경우에 행렬을 리턴값으로 두기 까다롭다는 것이다 (2차원 배열이니까.. 한가지 work around는 걍 out-value 파라미터를 사용하는것.. 하지만 그렇더라도 리턴값처럼 복사기반이 아니기 때문에 값의 정합성(오버라이팅 된다거나..)에 대해 항상 고민해야한다.)
따라서 자연스럽게 2차원배열 그 자체로 쓰는것보다 struct나 class로 빼는걸 생각하게 되는데.. 대입연산자나 생성자, 소멸자, 멤버함수등 생각할게 많아지고 코드의 단순함이 많이 훼손(?)된다.
vector의 vector를 사용하면 위의 리턴문제를 비교적 간단하게 해결할 수 있다. 아래 코드를 보자.
|
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
|
#include <bits/stdc++.h>
using namespace std;
typedef vector<vector<int>> matrix;
matrix mul(matrix A, matrix B)
{
int n = A.size(), m = A[0].size(), k = B[0].size();
matrix C(n, vector<int>(k));
for (int y = 0; y < n; y++)
for (int x = 0; x < k; x++)
for (int i = 0; i < m; i++)
C[y][x] += A[y][i] * B[i][x];
return C;
}
int main(void)
{
int n, m; scanf("%d %d", &n, &m);
matrix A(n, vector<int>(m));
for (int y = 0; y < n; y++)
for (int x = 0; x < m; x++)
scanf("%d", &A[y][x]);
int k; scanf("%d %d", &m, &k);
matrix B(m, vector<int>(k));
for (int y = 0; y < m; y++)
for (int x = 0; x < k; x++)
scanf("%d", &B[y][x]);
matrix C(n, vector<int>(k));
C = mul(A, B);
for (int y = 0; y < n; y++) {
for (int x = 0; x < k; x++) {
printf("%d ", C[y][x]);
}
printf("\n");
}
return 0;
}
|
cs |
연산자 오버로딩을 사용하면 mul 함수대신 * 기호를 사용할수도 있다. 다음을 보자.
|
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
|
#include <bits/stdc++.h>
using namespace std;
typedef vector<vector<int>> matrix;
matrix operator * (matrix A, matrix B)
{
int n = A.size(), m = A[0].size(), k = B[0].size();
matrix C(n, vector<int>(k));
for (int y = 0; y < n; y++)
for (int x = 0; x < k; x++)
for (int i = 0; i < m; i++)
C[y][x] += A[y][i] * B[i][x];
return C;
}
int main(void)
{
int n, m; scanf("%d %d", &n, &m);
matrix A(n, vector<int>(m));
for (int y = 0; y < n; y++)
for (int x = 0; x < m; x++)
scanf("%d", &A[y][x]);
int k; scanf("%d %d", &m, &k);
matrix B(m, vector<int>(k));
for (int y = 0; y < m; y++)
for (int x = 0; x < k; x++)
scanf("%d", &B[y][x]);
matrix C(n, vector<int>(k));
C = A * B;
for (int y = 0; y < n; y++) {
for (int x = 0; x < k; x++) {
printf("%d ", C[y][x]);
}
printf("\n");
}
return 0;
}
|
cs |
반응형
'Programming > Problem Solving' 카테고리의 다른 글
| C++ bigint class (1) | 2020.03.30 |
|---|---|
| 백준 9663번 N-Queen (0) | 2020.03.15 |
| C언어에서 표준입력으로 string 입력 받기 (0) | 2020.02.21 |
| 백준 팁모음 (0) | 2019.03.18 |
| 백준 제출시 오류유형 정리 (0) | 2019.03.18 |
