复建的一场,脑子还在重启中。
之前写的有很多东西都看不太懂了,有点艰难啊。
c 题:https://www.luogu.com.cn/problem/AT_abc400_c
long long 的 sqrt 应该这么写,不然会爆精度:
cpp
LL isqrt(LL x) {
if (x <= 1) {
return x;
}
LL l = 1, r = x, p = 0;
while(l <= r) {
LL mid = (l + r) >> 1;
if (mid <= x / mid) { // avoid overflow
l = mid + 1;
p = mid;
}
else {
r = mid - 1;
}
}
return p;
}
d 题:https://www.luogu.com.cn/problem/AT_abc400_d
多个状态,转移可能付出代价,最小代价。
最短路。
e 题:https://www.luogu.com.cn/problem/AT_abc400_e
看出来 1e6 就行,暴力枚举+二分查找。
感觉不太难?
f 题:https://www.luogu.com.cn/problem/AT_abc400_f
最开始的想法是每个颜色单独计算代价,但实际各个颜色段互相交错,染色时会互相影响代价。
区间,最优子结构可达成最优子结果,状态转移和代价计算都和端点有关。
区间 dp。
cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 810;
LL n, c[N], x[N];
LL f[N][N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> c[i], c[i + n] = c[i];
}
for (int i = 1; i <= n; i ++) {
cin >> x[i];
}
for (int i = 1; i <= n * 2; i ++) {
f[i][i] = x[c[i]] + 1;
}
for (int len = 2; len <= 2 * n; len ++) {
for (int l = 1, r = len; r <= 2 * n; l ++, r ++) {
f[l][r] = f[l][r - 1] + f[r][r];
for (int k = l; k < r; k ++) {
if (c[k] == c[r]) {
f[l][r] = min(f[l][r], f[l][k] + r - k + f[k + 1][r - 1]);
}
}
}
}
LL res = 1e18;
for (int l = 1, r = n; r <= 2 * n; l ++, r ++) {
res = min(res, f[l][r]);
}
cout << res;
return 0;
}
g 题:https://www.luogu.com.cn/problem/AT_abc400_g
看不太懂题解,先跳过,等水平归位了再补。