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
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
static const int INF = 1e9;
int n, m;
int grid[9][9];
vector<vector<unordered_map<string, int>>> memo;
static inline string normalizeProfile(const string& s) {
string normalized(s.size(), '0');
unsigned char remap[256] = {0};
char nextLabel = '1';
for (size_t i = 0; i < s.size(); ++i) {
char c = s[i];
if (c == '0') continue;
if (!remap[(unsigned char)c]) remap[(unsigned char)c] = nextLabel++;
normalized[i] = remap[(unsigned char)c];
}
return normalized;
}
static inline bool checkPass(const string& s) {
if (s[0] == '0') return true;
for (size_t i = 1; i < s.size(); ++i) if (s[i] == s[0]) return true;
return false;
}
static inline bool checkValid(const string& s) {
bool seen[256] = {false};
int cnt = 0;
for (char c : s) if (c != '0' && !seen[(unsigned char)c]) {
seen[(unsigned char)c] = true;
if (++cnt > 1) return false;
}
return true;
}
static inline string mergeWithLeft(const string& s) {
string ret = s;
char up = s[0];
char left = s.back();
ret.erase(ret.begin());
if (up == '0' && left == '0') ret.push_back('9');
else if (up == '0') ret.push_back(left);
else if (left == '0' || up == left) ret.push_back(up);
else {
for (char& c : ret) if (c == left) c = up;
ret.push_back(up);
}
return normalizeProfile(ret);
}
static inline string mergeNoLeft(const string& s) {
string ret = s; ret.erase(ret.begin());
char up = s[0];
ret.push_back(up == '0' ? '9' : up);
return normalizeProfile(ret);
}
int dfs(int x, int y, string cur) {
if (x == n) return checkValid(cur) ? 0 : INF;
cur = normalizeProfile(cur);
auto& cache = memo[x][y];
if (auto it = cache.find(cur); it != cache.end()) return it->second;
int best = INF;
int nx = x, ny = y + 1; if (ny >= m) { nx++; ny = 0; }
if (checkPass(cur)) {
string nxt = cur; nxt.erase(nxt.begin()); nxt.push_back('0');
best = min(best, dfs(nx, ny, nxt));
}
string nxtTake = (y ? mergeWithLeft(cur) : mergeNoLeft(cur));
best = min(best, dfs(nx, ny, nxtTake) + grid[x][y]);
if (checkValid(cur)) best = min(best, 0);
return cache[cur] = best;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> grid[i][j];
memo.assign(n, vector<unordered_map<string, int>>(m));
cout << dfs(0, 0, string(m, '0')) << '\n';
return 0;
}
|