행렬의 곱셈 순서에 따라서 필요한 곱셈의 수가 달라진다. 최소 곱셈 횟수를 찾는 것이 문제의 목표이다.
어떤 n이 주어졌을 때, A0A1...An-1에서 모든 곱셈의 경우를 보고 그 최소값을 찾아야된다.
곱셈의 결과를 저장하는 배열을 dp라고하고 dp[i][j]를 i부터 j번째까지의 최소 곱셈의 수를 저장한다.
행렬의 행과 열의 값을 페어로 저장하여, a에 저장한다. a[i].first는 Ai행렬의 행, a[i].second는 Ai행렬의 열의 값을 가진다.
이때 dp[i][i] = 0이고,
1 <= k < n 인 k와 0 <= j < k 인 j에 대해서 아래와 같은 식이 만족된다.
dp[i][i + k] = min(dp[i][i + j] + dp[i + j + 1][i + k] + a[i].first * a[i + j + 1].first * a[i + k].second, dp[i][i + k])
i부터 i + k까지의 행렬을 i부터 i +j 와 i+j+1부터 i+k까지의 행렬로 나누어 곱셈의 값을 계산한 후에 그 최소값을 구하면 된다.
아래는 나의 풀이이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<pair<long long, long long>> a;
int n;
long long dp[505][505];
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
long long l, r;
cin >> l >> r;
a.push_back(make_pair(l, r));
dp[i][i] = 0;
}
for (int k = 1; k < n; k++)
{
for (int i = 0; i + k < n; i++)
{
dp[i][i + k] = INT64_MAX;
for (int j = 0; j < k; j++)
{
dp[i][i + k] = min(dp[i][i + k - 1 - j] + dp[i + k - j][i + k] + a[i].first * a[i + k - j].first * a[i + k].second,
dp[i][i + k]);
}
}
}
cout << dp[0][n - 1] << endl;
return 0;
}
반응형
'Algorithm > 백준' 카테고리의 다른 글
백준 11724번 연결 요소의 개수 (c++) (0) | 2020.10.01 |
---|---|
백준 1764번 듣보잡 (c++) (0) | 2020.09.29 |
백준 1697번 숨바꼭질 (c++) (0) | 2020.09.29 |
백준 1012번 유기농 배추 (c++) (0) | 2020.09.29 |
백준 17626번 four squares (c++) (0) | 2020.09.27 |