cf 1063B. Labyrinth

传送门

给出一个地图,有空地以及障碍物。可以往四个方向走,但是左走的次数不能大于x次,右走的次数不能大于y次。

普通的bfs是不能做到最有的,因为有vis,那么到达一个点时可能存在两种走法:

  1. 右->上->左->上->右
  2. 左->上->右->下->右

也就说左走的次数太多了,导致浪费了右走的次数。
那么我们应该去贪心使得左走的次数和右走的次数都最少才是最优的。
假设从起点开始走,走到某一个位置,左走了(l)次,右走了(r)次,且起点和该点横坐标的差值为(a),有(r - l = a)
(b = l + r),表示总共走了多少次,那么(l = frac{b - a}{2}, r = frac{b + a}{2})
那么当且仅当(b)最小时,(l,r)才是最小的,那么优先队列进行bfs即可。

或者说用01bfs,因为上下走是不花费权值的,左右走是花费权值的,那么就用双端队列,上下走就插入首部,左右走就插入尾部,每次取首部元素。

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
using namespace std;
template<typename T = long long> inline T read() {
    T s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
    return s * f;
}
#ifdef ONLINE_JUDGE
#define qaq(...) ;
#define qwq(c) ;
#else
#define qwq(a, b) for_each(a, b, [=](int x){cerr << x << " ";}), cerr << std::endl
template <typename... T> void qaq(const T &...args) {
    auto &os = std::cerr;
    (void)(int[]){(os << args << " ", 0)...};
    os << std::endl;
}
#endif
const int N = 2e3 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
char s[N][N];
int dir[][2] = {0,1, -1,0, 0,-1, 1,0};
int mx_l, mx_r;
bool vis[N][N];
int ans = 0;
struct Node{
    int x, y, l, r;
};
void bfs(int stx, int sty, int n, int m){
    deque<Node> q;
    q.push_back({stx, sty, 0, 0});
    while(!q.empty()) {
        Node now = q.front(); q.pop_front();
        if(vis[now.x][now.y] || now.l > mx_l || now.r > mx_r) continue;
        s[now.x][now.y] = '+'; ans++;
        qaq(now.x, now.y);
        vis[now.x][now.y] = 1;
        for(int i = 0; i < 4; i++) {
            int xx = now.x + dir[i][0], yy = now.y + dir[i][1];
            if(xx < 1 || xx > n || yy < 1 || yy > m || s[xx][yy] == '*' || vis[xx][yy]) continue;
            if(i == 0) q.push_back({xx, yy, now.l, now.r + 1});
            else if(i == 2) q.push_back({xx, yy, now.l + 1, now.r});
            else q.push_front({xx, yy, now.l, now.r});
        }
    }
}
void solve(int kase){
    int n = read(), m = read();
    int r = read(), c = read();
    int x = read(), y = read();
    for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
    mx_l = x, mx_r = y;
    bfs(r, c, n, m);
    printf("%d
", ans);
}
const bool ISFILE = 0, DUO = 0;
int main(){
    clock_t start, finish; start = clock();
    if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
    if(DUO) {CASE solve(kase);} else solve(1);
    finish = clock(); 
    qaq("
Time:", (double)(finish - start) / CLOCKS_PER_SEC * 1000, "ms
");
    return 0;
}
I‘m Stein, welcome to my blog
原文地址:https://www.cnblogs.com/Emcikem/p/14700098.html