11.18题解
climb
首先我们有一个状态时 \(O(nV)\) 的 DP,即考虑到第 i 个点,当前高度是 j 的最小代价。
这个状态太大了,我们考虑哪些状态时冗余的。
考虑我一个点经过调整,如果前一个点确定是 t,那么当前这个点可能且只可能是:t - d, t + d, a_i。
那么这个东西是一个 a_i + kd 的形式的,我们就可以将状态精简为 \(O(n^3)\) 的。
然后考虑到这个转移是一个滑动窗口的形式,则最终复杂度是 \(O(n^3)\)。
代码
#include <bits/stdc++.h>
using namespace std;
namespace myb {
#define int long long
const int N = 305;
int a[N];
int f[2][N * N * 2];
void solve() {
int n, d;
cin >> n >> d;
for (int i = 1;i <= n;i++) cin >> a[i];
vector<int> x;
for (int i = 1;i <= n;i++) {
// if (d == 0) {
// x.push_back(a[i]);
// continue;
// }
for (int j = -n;j <= n;j++) {
if (a[i] + 1ll * j * d < 0) continue;
x.push_back(a[i] + 1ll * j * d);
}
}
sort(x.begin(), x.end());
x.erase(unique(x.begin(), x.end()), x.end());
int m = x.size();
for (int i = 0;i <= 1;i++) {
for (int j = 0;j < m;j++) {
f[i][j] = 1e16;
}
}
int ind = 0;
for (int i = 0;i < m;i++) {
if (x[i] == a[1]) f[ind][i] = 0;
}
ind = 1 - ind;
for (int i = 2;i <= n;i++, ind = 1 - ind) {
// cout << i << ":\n";
// cout << i << " " << ind << "\n";
deque<int> q;
int pos = 0;
for (int j = 0;j < m;j++) {
while (pos < m && x[pos] <= x[j] + d) {
while (q.size() && f[1 - ind][q.back()] >= f[1 - ind][pos]) q.pop_back();
q.push_back(pos);
pos++;
}
while (q.size() && x[q.front()] < x[j] - d) q.pop_front();
if (q.size() == 0) break;
f[ind][j] = f[1 - ind][q.front()] + abs(a[i] - x[j]);
// cout << f[ind][j] << " ";
// cout << x[j] << ": " << f[i][j] << "\n";
}
// cout << "\n";
// cout << "?\n";
}
// cout << ind << "\n";
for (int i = 0;i < m;i++) {
if (x[i] == a[n]) {
if (f[1 - ind][i] > 1e15) cout << "-1\n";
else cout << f[1 - ind][i] << "\n";
return ;
}
}
}
void main() {
int T;
T = 1;
// cin >> T;
while (T--) {
solve();
}
}
}
signed main() {
freopen("climb.in", "r", stdin);
freopen("climb.out", "w", stdout);
myb::main();
return 0;
}
fun game
首先清掉是别人子串的字符串,这些一定无用。
然后我们需要注意到一个关键性质:完成以上操作后,一定不会有一个字串绕过最终答案的那个环一整圈。
因为如果绕过去了,就意味着所有串都是他的子串。
然后我们就是一个字符串拼接的顺序问题,这个直接状压 DP。
line game
可以发现,我们要选择的线不会交叉,i 和 \(p_i\) 是分别递增的。
那我可以令 \(f_i\) 是选择第 i 条边删去,前面的全部都删掉了的最小花费,那么这个就应该从最近的一个 j,满足 \(p_j < p_i\) 转移而来。
那么我们怎么找到这个 j 呢?

浙公网安备 33010602011771号