CF1753D The Beach

CF1753D The Beach

题目简意

一个 \(n\times m\) 的网格图,有的格子有障碍,有的格子为空,有的格子上有床(床占上下左右相邻的两格)。现在你可以执行两种操作:

  1. 将一个床旋转一格,操作代价为 \(p\)

  2. 将一个床沿它的方向平移一格,操作代价为 \(q\)

形式化地定义旋转一格和平移一格:设床所占的两格坐标是 \(\{(x_1,y_1),(x_2,y_2)\}(|x_1-x_2|+|y_1-y_2|=1)\) ,旋转一格后床所占的两格坐标是 \(\{(x_1,y_1),(x_3,y_3)\}(|x_1-x_3|+|y_1-y_3|=1,|x_2-x_3|=1,|y_2-y_3|=1)\),平移一格后床所占的两格坐标是 \(\{(x_1,y_1),(x_3,y_3)\}(|x_1-x_3|+|y_1-y_3|=1,\max(|x_2-x_3|,|y_2-y_3|)=2)\)。需要保证每次操作后,床所在的格子没有障碍。

现在你要再往网格图里加一张床,问最少的操作代价是多少,若无解输出 \(-1\)

\(1\le n, m\le 3\times10^5,1\le n\times m\le 3\times10^5,1\le p,q\le 10^9\)

题解

要加一张床,无非是通过一些操作使得空格凑在一起,那可以想到一个 dp :\(f_{i,j}\) 表示把 \((i,j)\) 这个格子变成空格子的最小代价。如果 \((i,j)\) 初始为空,那么 \(f(i,j)=0\) ;如果是障碍,那么 \(f(i,j)=+\infty\);如果是床,那么需要通过操作挪床。两个操作的本质都是固定床的一端,移动另一端,所以 \((i,j)\) 一定是挪动的一端,那转移就只有 \(3\) 种情况,分类讨论即可。

dp 顺序怎么办呢?容易发现这个 dp 相当于是一个最短路,直接以所有空格子为起点,跑多源 dij 即可。

答案就是 \(\min_{|x_1-x_2|+|y_1-y_2|=1}\{f_{x_1,y_1}+f_{x_2,y_2}\}\)

直接实现就可以通过此题,但是有一个问题,这个题是要凑出两个空格子,而跑最短路的时候是跑的一个空格,那会不会出现最后的答案里,同一张床被操作两次的情况呢(显然是不合法的操作)?答案是否定的,因为一旦出现了这种情况,这张床周围至少有 \(2\) 个空格,那么最多只需要操作这张床一次就可以把两个空格挪到一起。即不合法的答案一定不优。

代码

#include <bits/stdc++.h>
#define re(i, x, y) for (int i = (x); i < (y); ++i) 
#define rep(i, x, y) for (int i = (x); i <= (y); ++i)
#define repp(i, x, y, d) for (int i = (x); i <= (y); i += (d))
#define reep(i, x, y) for (int i = (x); i <= (y); i <<= 1)
#define pe(i, x, y) for (int i = (x) - 1; i >= (y); --i)
#define per(i, x, y) for (int i = (x); i >= (y); --i)
#define rep_e(i, u) for (int i = head[(u)]; i; i = e[i].nxt)
#define vi vector<int>
#define vL vector<LL>
#define vii vector<pii> 
#define viL vector<piL>
#define vLi vector<pLi> 
#define vLL vector<pLL>
#define eb emplace_back
#define pb pop_back
#define mp make_pair
#define pii pair<int, int>
#define piL pair<int, LL>
#define pLi pair<LL, int>
#define pLL pair<LL, LL>
#define lowbit(x) ((x) & (-(x)))
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define debug(x) cout << #x << " = " << x << endl
using namespace std;
typedef unsigned int ui;
typedef long long LL;
typedef unsigned long long ULL;
typedef double db;
#define getchar() (SB == TB && (TB = (SB = BB) + fread(BB, 1, 1 << 16, stdin), SB == TB) ? EOF : *SB++)
char BB[1 << 16], *SB = BB, *TB = BB;
template<typename T> void read(T &n) {
	T w = 1;
	n = 0;
	char ch = getchar();
	for ( ; !isdigit(ch); ch = getchar()) {
		if (ch == '-') {
			w = -1;
		}
	}
	for ( ; isdigit(ch); ch = getchar()) {
		n = n * 10 + (ch & 15);
	}
	n *= w;
}
template<typename T> void chkmn(T &a, const T &b) { 
	a = a > b ? b : a; 
}
template<typename T> void chkmx(T &a, const T &b) { 
	a = a < b ? b : a; 
}

int MOD;
int adt(const LL &a) { 
	return (a % MOD + MOD) % MOD; 
} 
int inc(const int &a, const int &b) { 
	return a + b >= MOD ? a + b - MOD : a + b; 
}
int dec(const int &a, const int &b) { 
	return a - b < 0 ? a - b + MOD : a - b; 
}
int mul(const int &a, const int &b) { 
	return 1LL * a * b % MOD; 
}
int sqr(const int &a) { 
	return 1LL * a * a % MOD; 
}
void Adt(LL &a) {
	a = (a % MOD + MOD) % MOD;
}
void Inc(int &a, const int &b) { 
	a = a + b >= MOD ? a + b - MOD : a + b;
}
void Dec(int &a, const int &b) { 
    a = a - b < 0 ? a - b + MOD : a - b;
}
void Mul(int &a, const int &b) { 
	a = 1LL * a * b % MOD; 
}
void Sqr(int &a) { 
	a = 1LL * a * a % MOD; 
}
int fsp(int a, int x = MOD - 2) {
	int res = 1;
	for ( ; x; x >>= 1, Sqr(a)) {
		if (x & 1) {
			Mul(res, a);
		}
	}
	return res;
}

const int maxn = 3e5 + 5, dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
const LL INF = 1e18;
int n, m, p, q;
LL dis[maxn];
bool vis[maxn];
string s[maxn];

struct node {
    LL d;
    int x, y;
    node(LL d = 0, int x = 0, int y = 0) : d(d), x(x), y(y) {}
} d[maxn];
bool operator < (node x, node y) {
    return x.d > y.d;
}
priority_queue<node> pq;

int main() {
	
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> m >> p >> q;
    auto id = [&] (int x, int y) {
        return (x - 1) * m + y;
    };
    memset(dis, 0x3f, sizeof(dis));
    rep(i, 1, n) {
        cin >> s[i];
        re(j, 0, m) {
            if (s[i][j] == '.') {
                dis[id(i, j + 1)] = 0;
                pq.emplace(0, i, j + 1);
            }
        }
    }
    for ( ; !pq.empty(); ) {
        int x = pq.top().x, y = pq.top().y;
        pq.pop();
        if (vis[id(x, y)]) {
            continue ;
        }
        vis[id(x, y)] = 1;
        re(i, 0, 4) {
            int xx = x + dx[i], yy = y + dy[i];
            if (xx >= 1 && yy >= 1 && xx <= n && yy <= m) {
                if (s[xx][yy - 1] == 'L') {
                    int c = i < 2 ? p : q;
                    if (dis[id(xx, yy + 1)] > dis[id(x, y)] + c) {
                        dis[id(xx, yy + 1)] = dis[id(x, y)] + c;
                        pq.emplace(dis[id(xx, yy + 1)], xx, yy + 1);
                    }
                }
                else if (s[xx][yy - 1] == 'R') {
                    int c = i < 2 ? p : q;
                    if (dis[id(xx, yy - 1)] > dis[id(x, y)] + c) {
                        dis[id(xx, yy - 1)] = dis[id(x, y)] + c;
                        pq.emplace(dis[id(xx, yy - 1)], xx, yy - 1);
                    }
                }
                else if (s[xx][yy - 1] == 'D') {
                    int c = i < 2 ? q : p;
                    if (dis[id(xx - 1, yy)] > dis[id(x, y)] + c) {
                        dis[id(xx - 1, yy)] = dis[id(x, y)] + c;
                        pq.emplace(dis[id(xx - 1, yy)], xx - 1, yy);
                    }
                }
                else if (s[xx][yy - 1] == 'U') {
                    int c = i < 2 ? q : p;
                    if (dis[id(xx + 1, yy)] > dis[id(x, y)] + c) {
                        dis[id(xx + 1, yy)] = dis[id(x, y)] + c;
                        pq.emplace(dis[id(xx + 1, yy)], xx + 1, yy);
                    }
                }
            }
        }
    }
    LL ans = INF;
    rep(i, 1, n) {
        rep(j, 1, m) {
            if (i < n) {
                chkmn(ans, dis[id(i, j)] + dis[id(i + 1, j)]);
            }
            if (j < m) {
                chkmn(ans, dis[id(i, j)] + dis[id(i, j + 1)]);
            }
        }
    }
    printf("%lld\n", ans == INF ? -1 : ans);
	return 0;
}
posted @ 2022-10-23 22:21  Sword_K  阅读(47)  评论(0)    收藏  举报