-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path3441.minimum-cost-good-caption.cpp
More file actions
110 lines (97 loc) · 4.01 KB
/
3441.minimum-cost-good-caption.cpp
File metadata and controls
110 lines (97 loc) · 4.01 KB
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#
# @lc app=leetcode id=3441 lang=cpp
#
# [3441] Minimum Cost Good Caption
#
# @lc code=start
class Solution {
public:
string minCostGoodCaption(string caption) {
int n = caption.size();
if (n < 3) return "";
const int INF = 1e9;
// Forward DP: dp[i][k][c] - k=0,1,2 for 1,2,>=3 chars in group with char c
vector<vector<vector<int>>> dp(n + 1, vector<vector<int>>(3, vector<int>(26, INF)));
vector<int> dpB(n + 1, INF);
dpB[0] = 0;
for (int i = 0; i < n; i++) {
int ch = caption[i] - 'a';
int minValid = *min_element(dp[i][2].begin(), dp[i][2].end());
for (int c = 0; c < 26; c++) {
int cost = abs(ch - c);
dp[i + 1][0][c] = min({dp[i + 1][0][c], dpB[i] + cost, minValid + cost});
dp[i + 1][1][c] = min(dp[i + 1][1][c], dp[i][0][c] + cost);
dp[i + 1][2][c] = min({dp[i + 1][2][c], dp[i][1][c] + cost, dp[i][2][c] + cost});
}
dpB[i + 1] = *min_element(dp[i + 1][2].begin(), dp[i + 1][2].end());
}
int minCost = dpB[n];
if (minCost >= INF) return "";
// Backward DP for reconstruction
vector<vector<vector<int>>> dp2(n + 1, vector<vector<int>>(3, vector<int>(26, INF)));
for (int c = 0; c < 26; c++) dp2[n][2][c] = 0;
for (int i = n - 1; i >= 0; i--) {
int ch = caption[i] - 'a';
int minStart = *min_element(dp2[i + 1][0].begin(), dp2[i + 1][0].end());
for (int c = 0; c < 26; c++) {
int cost = abs(ch - c);
dp2[i][0][c] = min(dp2[i][0][c], dp2[i + 1][1][c] + cost);
dp2[i][1][c] = min(dp2[i][1][c], dp2[i + 1][2][c] + cost);
dp2[i][2][c] = min({dp2[i][2][c], dp2[i + 1][2][c] + cost, minStart + cost});
}
}
// Greedy reconstruction
string result;
int state = -1, curChar = -1;
for (int i = 0; i < n; i++) {
int ch = caption[i] - 'a';
if (state == -1) {
int baseVal = dpB[i];
for (int c = 0; c < 26; c++) {
int cost = abs(ch - c);
if (baseVal + cost + dp2[i + 1][0][c] == minCost) {
result += (char)('a' + c);
state = 0; curChar = c;
break;
}
}
} else if (state == 0) {
result += (char)('a' + curChar);
state = 1;
} else if (state == 1) {
result += (char)('a' + curChar);
state = 2;
} else {
int cost = abs(ch - curChar);
bool extended = false;
if (dp[i][2][curChar] + cost + dp2[i + 1][2][curChar] == minCost) {
for (int c = 0; c < curChar; c++) {
int newCost = abs(ch - c);
if (dp[i][2][curChar] + newCost + dp2[i + 1][0][c] == minCost) {
result += (char)('a' + c);
state = 0; curChar = c;
extended = true;
break;
}
}
if (!extended) {
result += (char)('a' + curChar);
extended = true;
}
} else {
for (int c = 0; c < 26; c++) {
int newCost = abs(ch - c);
if (dp[i][2][curChar] + newCost + dp2[i + 1][0][c] == minCost) {
result += (char)('a' + c);
state = 0; curChar = c;
extended = true;
break;
}
}
}
}
}
return result;
}
};
# @lc code=end