๐ ์ด๋ณด์์ฉ ๊ฐ์ด๋ โMinimum Cost Path with Teleportationsโ - LeetCode 3651 (C++, Python, JavaScript)
Source: Dev.to
๋ฒ์ญ์ ์งํํ๋ ค๋ฉด ๋ฒ์ญํ๊ณ ์ ํ๋ ๋ณธ๋ฌธ ํ ์คํธ๋ฅผ ์ ๊ณตํด ์ฃผ์๊ฒ ์ด์? ํ์ฌ ์ ๊ณต๋ ๋ด์ฉ์ ์์ค ๋งํฌ๋ฟ์ด๋ผ ๋ฒ์ญํ ํ ์คํธ๊ฐ ์์ต๋๋ค. ํ ์คํธ๋ฅผ ์๋ ค์ฃผ์๋ฉด ํ๊ตญ์ด๋ก ๋ฒ์ญํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
Problem Overview
๊ทธ๋ฆฌ๋๋ฅผ ํ์ํ๋ ๊ฒ์ ๊ณ ์ ์ ์ธ ์ฝ๋ฉ ๋ฌธ์ ์ด์ง๋ง, ํ
๋ ํฌํ
์ด์
์ ์ถ๊ฐํ๋ฉด ๊ฒ์์ด ์์ ํ ๋ฐ๋๋๋ค.
๋ค์์ด ์ฃผ์ด์ง๋๋ค:
- ๊ฐ ์
์ ๋น์ฉ์ด ๋ค์ด ์๋
m x nํฌ๊ธฐ์ 2์ฐจ์ ๊ทธ๋ฆฌ๋. - ํ
๋ ํฌํธํ ์ ์๋ ์ต๋ ํ์๋ฅผ ๋ํ๋ด๋ ์ ์
k. - ๋ ๊ฐ์ง ์ด๋ ๊ท์น:
- ํ์ค ์ด๋ โ ์ค๋ฅธ์ชฝ ๋๋ ์๋์ชฝ์ผ๋ก ์ด๋ํ๋ฉฐ, ๋ชฉ์ ์ง ์ ์ ๊ฐ๋งํผ ๋น์ฉ์ด ๋ญ๋๋ค.
- ํ ๋ ํฌํ ์ด์ โ ํ์ฌ ์ ์ ๊ฐ๋ณด๋ค **โค**์ธ ๋ชจ๋ ์ ๋ก ์ ํํ ์ ์์ผ๋ฉฐ, ๋น์ฉ์ 0์ ๋๋ค.
Goal: ์ผ์ชฝ ์ ์
(0,0)์์ ์ค๋ฅธ์ชฝ ์๋ ์
(mโ1,nโ1)๊น์ง ์ด๋ํ๋ ์ต์ ์ด ๋น์ฉ์ ๊ณ์ฐํ์ธ์.
์ ๊ทผ๋ฒ
ํ ๋ ํฌํธ ์๋ ํ์ค DP
ํ ๋ ํฌํธ๊ฐ ์์ผ๋ฉด ๋ฌธ์ ๋ ๊ฐ๋จํ DP๋ก ์ถ์๋ฉ๋๋ค:
dp[i][j] = grid[i][j] + min(dp[iโ1][j], dp[i][jโ1])
ํ ๋ ํฌํธ ๋์
ํ
๋ ํฌํธ๋ ๋น์ฉ์ด ๋ค์ง ์๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ฅํ์ง๋ง, ํ์ฌ ์
์ ๊ฐ๋ณด๋ค ํฌ์ง ์์ ์
๋ง์ ๋ชฉํ๋ก ํ ์ ์์ผ๋ฉฐ, ์ต๋ k๋ฒ๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์ธต(๋๋ โ๋ผ์ด๋โ) ๋ณ๋ก ํ ๋ ํฌํธ ์ฌ์ฉ ํ์์ ๋ฐ๋ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค:
- ํ
๋ ํฌํธ ์ฌ์ฉ ํ์
t = 0 โฆ k๋ง๋ค ๋ชจ๋ ๊ฐ๋ฅํ ์ ๊ฐ์ ๋๋ฌํ๋ ๊ฐ์ฅ ์ ๋ ดํ ๋น์ฉ์ ์ ์งํฉ๋๋ค. - ์ ๋ฏธ ์ต์ ๋ฐฐ์ด
suf_min_f[value]๋ ๊ฐ์ด โฅvalue์ธ ์ ์ค ๋๋ฌ ๋น์ฉ์ด ๊ฐ์ฅ ๋ฎ์ ๊ฐ์ ์ ์ฅํฉ๋๋ค. ์ด๋ฅผ ํตํด โ๊ฐ์ดx์ธ ์ ๋ก ํ ๋ ํฌํธํ๋ ๊ฒ์ด ๋ ์ ๋ ดํ๊ฐ?โ๋ฅผO(1)์ ๋ตํ ์ ์์ต๋๋ค. - ๊ทธ๋ฆฌ๋๋ฅผ ํโ๋จ์๋ก ์ค์บํ๋ฉด์ ๋ค์์ ์
๋ฐ์ดํธํฉ๋๋ค:
standard_moveโ ์ผ์ชฝ ๋๋ ์์ชฝ์์ ์ค๋ ๋น์ฉ์ ํ์ฌ ์ ๊ฐ์ ๋ํ ๊ฐ.teleport_moveโsuf_min_f[x](๊ฐ์ด โฅx์ธ ๋๋ฌ ๊ฐ๋ฅํ ์ ์ค ๊ฐ์ฅ ์ข์ ๋น์ฉ).- ์ด ๋ ๊ฐ ์ค ์ต์๊ฐ ํ์ฌ ์ ์ ์๋ก์ด ๋น์ฉ์ด ๋ฉ๋๋ค.
- ํน์
t์ ๋ํด ์ ์ฒด ๊ทธ๋ฆฌ๋๋ฅผ ์ฒ๋ฆฌํ ํ, ๋ค์ ๋ฐ๋ณต์ ์ํดsuf_min_f๋ฅผ ๋ค์ ๊ตฌ์ถํฉ๋๋ค.
์๊ณ ๋ฆฌ์ฆ์ suf_min_f๊ฐ ๋ฐ๋ณต ์ฌ์ด์ ๋ณํ์ง ์์ผ๋ฉด ์กฐ๊ธฐ์ ์ข
๋ฃ๋ฉ๋๋ค.
๋ณต์ก๋
- ์๊ฐ:
O(k * m * n)โ ๊ฐ ์ธต๋ง๋ค ๊ทธ๋ฆฌ๋๋ฅผ ํ ๋ฒ์ฉ ์ค์บํฉ๋๋ค. - ๊ณต๊ฐ:
O(mx + n)์ฌ๊ธฐ์mx๋ ์ ๊ฐ์ ์ต๋๊ฐ(์ ๋ฏธ ๋ฐฐ์ด์ฉ)์ด๋ฉฐ, ์ ํ DP ํ์ ์ถ๊ฐ๋ก ์ฌ์ฉํฉ๋๋ค.
์์
grid = [[1,3,3],
[2,5,4],
[4,3,5]]
k = 2
(0,0)์์ ๋น์ฉ0์ผ๋ก ์์ํฉ๋๋ค.- ์๋๋ก ์ด๋ํ์ฌ
(1,0)โ ๋น์ฉ2. - ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋ํ์ฌ
(1,1)โ ๋น์ฉ7. (1,1)(๊ฐ5)์์(2,2)(๊ฐ5)๋ก ๋ฌด๋ฃ ํ ๋ ํฌํธํฉ๋๋ค.- ๋ชฉ์ ์ง์ ๋๋ฌํ์ผ๋ฉฐ ์ด ๋น์ฉ์
7์ ๋๋ค.
๋ต์ 7์
๋๋ค.
์๋ฃจ์ ๊ตฌํ
C++ (GNUโC++17)
class Solution {
public:
int minCost(vector<vector<int>>& grid, int k) {
int m = grid.size(), n = grid[0].size();
// Edge case: free teleport possible
if (k > 0 && grid[0][0] >= grid[m - 1][n - 1]) return 0;
int mx = 0;
for (auto& row : grid)
for (int v : row) mx = max(mx, v);
const int INF = 2e9;
vector<int> suf_min_f(mx + 2, INF);
vector<int> f(n + 1, INF);
for (int t = 0; t <= k; ++t) {
vector<int> min_f(mx + 1, INF);
vector<int> new_f(n + 1, INF);
if (t == 0) new_f[1] = 0; // start cost
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
int x = grid[i][j];
int standard = min(new_f[j], new_f[j + 1]) + x;
if (i == 0 && j == 0 && t == 0) standard = 0;
new_f[j + 1] = min(standard, suf_min_f[x]);
min_f[x] = min(min_f[x], new_f[j + 1]);
}
}
f = new_f;
// rebuild suffix minima
vector<int> new_suf(mx + 2, INF);
for (int v = mx; v >= 0; --v)
new_suf[v] = min(new_suf[v + 1], min_f[v]);
if (suf_min_f == new_suf) break;
suf_min_f.swap(new_suf);
}
return f[n];
}
};
Python 3
class Solution:
def minCost(self, grid: list[list[int]], k: int) -> int:
m, n = len(grid), len(grid[0])
if k > 0 and grid[0][0] >= grid[m - 1][n - 1]:
return 0
mx = max(max(row) for row in grid)
INF = float('inf')
suf_min_f = [INF] * (mx + 2)
f = [INF] * (n + 1)
for t in range(k + 1):
min_f = [INF] * (mx + 1)
new_f = [INF] * (n + 1)
if t == 0:
new_f[1] = 0 # start cost
for i in range(m):
for j in range(n):
x = grid[i][j]
standard = min(new_f[j], new_f[j + 1]) + x
if i == 0 and j == 0 and t == 0:
standard = 0
new_f[j + 1] = min(standard, suf_min_f[x])
min_f[x] = min(min_f[x], new_f[j + 1])
f = new_f
# rebuild suffix minima
new_suf = [INF] * (mx + 2)
for v in range(mx, -1, -1):
new_suf[v] = min(new_suf[v + 1], min_f[v])
if suf_min_f == new_suf:
break
suf_min_f = new_suf
return f[n]
JavaScript (Node.js)
/**
* @param {number[][]} grid
* @param {number} k
* @return {number}
*/
var minCost = function(grid, k) {
const m = grid.length, n = grid[0].length;
if (k > 0 && grid[0][0] >= grid[m - 1][n - 1]) return 0;
let mx = 0;
for (let row of grid)
for (let v of row) mx = Math.max(mx, v);
const INF = Number.MAX_SAFE_INTEGER;
let sufMinF = new Array(mx + 2).fill(INF);
let f = new Array(n + 1).fill(INF);
for (let t = 0; t <= k; ++t) {
const minF = new Array(mx + 1).fill(INF);
const newF = new Array(n + 1).fill(INF);
if (t === 0) newF[1] = 0; // start cost
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
const x = grid[i][j];
const standard = Math.min(newF[j], newF[j + 1]) + x;
const best = Math.min(standard, sufMinF[x]);
newF[j + 1] = best;
minF[x] = Math.min(minF[x], best);
}
}
f = newF;
// rebuild suffix minima
const nextSuf = new Array(mx + 2).fill(INF);
for (let v = mx; v >= 0; --v)
nextSuf[v] = Math.min(nextSuf[v + 1], minF[v]);
if (JSON.stringify(sufMinF) === JSON.stringify(nextSuf)) break;
sufMinF = nextSuf;
}
return
f[n];
};
ํต์ฌ ์์
- ์ํ ํ์ฅ (ํ ๋ ํฌํธ ํ์ ์ฐจ์์ ์ถ๊ฐ)์ผ๋ก ๊ฐ ํ์ฉ๋ ํ ๋ ํฌํธ๋ง๋ค ๋์ผํ DP ๋ก์ง์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ ๋ฏธ ์ต์๊ฐ์ ์ฌ์ฉํ๋ฉด โ๊ฐ์ด โฅโฏx์ธ ๋ชจ๋ ์
์ค ๊ฐ์ฅ ์ ๋ ดํ ๋น์ฉโ์ ๋ํด
O(1)์กฐํ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. - ๊ณต๊ฐ ์ต์ ํ: ์ด์ ํ ๋ ํฌํธ ํ์์ ๊ฒฐ๊ณผ๋ง ํ์ํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ ํ์ผ๋ก ์ ์งํฉ๋๋ค.
์ด ํจํด์ ๋ฐฐ๋ฌ ๋๋ก ์ด (๋น์ฉ์ด ๋ง์ด ๋๋) ์ง์ ์ฃผํ์ด๋ ๊ณ ๊ณ ๋ ํจ๋ ์ฌ์ด๋ฅผ (๋ฌด๋ฃ์ด์ง๋ง ์ ํ๋) ๋นํํ ์ ์๋ ์ค์ ๋ผ์ฐํ ๋ฌธ์ ๋ฑ์์ ๋ง์ด ๋ํ๋ฉ๋๋ค.