题解:P17679 [IO 2025 #4] 黑客任务
DP 板刷计划第三题。官评蓝,自评绿青之间。
这个题,比较简单的矩阵优化 DP 吧。不知道为啥蓝,我一眼秒的 DP 青顶天了。本文定义
首先考虑暴力 DP 怎么做。设
我们定义
形式化的,定义
那么现在我们得到了一个
接着上矩阵加速。构造转移矩阵
然后考虑怎么推出这个转移矩阵。其实比较简单,令
所以复杂度优化为
#include <bits/stdc++.h>
#define rep(i, l, r) for(int i = (l); i <= (r); i ++ )
#define per(i, l, r) for(int i = (l); i >= (r); i -- )
#define frein(s) freopen(s, "r", stdin)
#define freout(s) freopen(s, "w", stdout)
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e5 + 5;
const int S = 26 + 5;
const int INF = 0x3f3f3f3f3f3f3f3f;
int n, k, p[3][9], cnt, ans = INF;
pair<int, int> pos[S];
string s[N], kyb[3];
int dis(pair<int, int> x, pair<int, int> y)
{ return abs(x.first - y.first) + abs(x.second - y.second); }
struct Matrix {
int m[S][S];
Matrix() { memset(m, 0x3f, sizeof m); }
auto operator [] (int x) { return m[x]; }
} mt;
Matrix operator * (Matrix a, Matrix b) {
Matrix c;
rep(i, 1, 26) rep(k, 1, 26)
rep(j, 1, 26) c[i][j] = min(a[i][k] + b[k][j], c[i][j]);
return c;
}
Matrix qpow(Matrix a, int b) {
Matrix res;
rep(i, 1, 26) res[i][i] = 0;
for(; b; a = a * a, b >>= 1) if(b & 1) res = res * a;
return res;
}
signed main() {
ios :: sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> k;
rep(i, 1, n) cin >> s[i];
cin.ignore();
rep(i, 0, 2) getline(cin, kyb[i]);
rep(i, 0, 2) rep(j, 0, 8) {
if(kyb[i][j] != ' ') {
pos[kyb[i][j] - 'a'] = make_pair(i, j);
p[i][j] = ++ cnt;
}
}
rep(i, 1, n) {
int res = 0;
rep(j, 0, (int)s[i].size() - 2) res += dis(pos[s[i][j] - 'a'], pos[s[i][j + 1] - 'a']);
rep(j, 0, 2) rep(k, 0, 8) {
int p1 = p[j][k];
pair<int, int> ps = pos[s[i].back() - 'a'];
int p2 = p[ps.first][ps.second];
mt[p1][p2] = min(mt[p1][p2], dis(make_pair(j, k), pos[s[i].front() - 'a']) + res);
}
}
mt = qpow(mt, k);
rep(i, 1, 26) rep(j, 1, 26) ans = min(ans, mt[i][j]);
cout << ans << endl;
return 0;
}