P1037 易形迷宫(maze)
我们可以转化一下题面,把胸口碎大石的功能换成幽灵,可以直接穿透石头,那么我们可以把炸碎石头改成可以向 \(8\) 个方向随便走 \(k - 1\) 步,然后我们直接 \(dij\) 即可
#include <bits/stdc++.h>
using namespace std;
using Pii = pair<int, int>;
const int N = 2500 + 5;
struct node {
int cnt, now;
};
struct qnode {
int x, y, cnt, now;
bool operator < (const qnode &e) const {
return e.cnt == cnt ? now < e.now : cnt > e.cnt;
}
};
int n, m, k, sx, sy, tx, ty;
int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
vector<char> a[N];
vector<node> dis[N];
priority_queue<qnode> q;
void Record(int opt, int x, int y, int cnt, int now) {
if (x < 1 || y < 1 || x > n || y > m) {
return ;
}
if (opt == 1 && a[x][y] == '#' && !now) {
cnt++, now = k;
}
now = max(0, now - 1);
if ((cnt == dis[x][y].cnt && now > dis[x][y].now) || cnt < dis[x][y].cnt) {
dis[x][y] = (node){cnt, now};
q.push({x, y, cnt, now});
}
}
void dij() {
Record(1, sx, sy, 0, 0);
while (!q.empty()) {
qnode cur = q.top();
q.pop();
if ((dis[cur.x][cur.y].cnt == cur.cnt && dis[cur.x][cur.y].now > cur.now) || cur.cnt > dis[cur.x][cur.y].cnt) {
continue;
}
for (int i = 0; i < 4; i++) {
Record(1, cur.x + dx[i], cur.y + dy[i], cur.cnt, cur.now);
}
if (!cur.now) {
continue;
}
for (int i = 4; i < 8; i++) {
Record(2, cur.x + dx[i], cur.y + dy[i], cur.cnt, cur.now);
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
freopen("maze.in", "r", stdin);
freopen("maze.out", "w", stdout);
cin >> n >> m >> k;
cin >> sx >> sy;
cin >> tx >> ty;
for (int i = 0; i <= n + 1; i++) {
a[i].resize(m + 1);
dis[i].resize(m + 1);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
dis[i][j] = {(int)(1e9), (int)(-1e9)};
}
}
dij();
cout << dis[tx][ty].cnt;
return 0;
}
训练山猫(lynx)
我们可以先将每个点按照高度排序,然后设 \(dp_i\) 表示从第 \(i\) 个点出发最大可以走多少步
那么我们可以预处理出如果将 \(i\) 相邻的连通块中最大的点,假设为 \(j\) 那么就有转移 \(dp_i = dp_j + dist(i, j)\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
struct node {
int h, id;
}a[N];
int n, dep[N], dp[N][25], f[N], fa[N], b[N];
vector<int> g[N];
void dfs(int u, int f) {
dep[u] = dep[f] + 1;
dp[u][0] = f;
for (int i = 1; (1 << i) <= dep[u]; i++) {
dp[u][i] = dp[dp[u][i - 1]][i - 1];
}
for (auto v : g[u]) {
if (v == f) continue;
dfs(v, u);
}
}
int lca(int a, int b) {
if (dep[a] < dep[b]) swap(a, b);
for (int i = 20; i >= 0; i--) {
if (dep[dp[a][i]] >= dep[b]) {
a = dp[a][i];
}
}
if (a == b) return a;
for (int i = 20; i >= 0; i--) {
if (dp[a][i] != dp[b][i]) {
a = dp[a][i];
b = dp[b][i];
}
}
return dp[a][0];
}
int dist(int a, int b) {
return dep[a] + dep[b] - 2 * dep[lca(a, b)];
}
bool cmp(node _x, node _y) {
return _x.h < _y.h;
}
int find(int x) {
if (fa[x] == x) {
return x;
}
return fa[x] = find(fa[x]);
}
signed main() {
freopen("lynx.in", "r", stdin);
freopen("lynx.out", "w", stdout);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].h;
a[i].id = i;
b[i] = a[i].h;
}
for (int i = 1, u, v; i < n; i++) {
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++) {
fa[i] = i;
}
f[a[1].id] = 0;
for (int i = 2; i <= n; i++) {
for (auto cur : g[a[i].id]) {
if (b[a[i].id] > b[cur]) {
f[a[i].id] = max(f[a[i].id], f[find(cur)] + dist(find(cur), a[i].id));
fa[find(cur)] = a[i].id;
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
ans = max(ans, f[i]);
}
cout << ans;
return 0;
}
标签:20241015,cnt,cur,int,now,dp,dis
From: https://www.cnblogs.com/libohan/p/18468421