• 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
  • 相关阅读:
    第010讲~第011讲:一个打了激素的数组
    练习15--阅读文件
    第007讲~第009讲:了不起的分支和循环
    第006讲:Python之常用操作符
    第005讲:闲聊之python的数据类型
    练习14--提示和传递
    第004讲:改进我们的小游戏
    ICPC Central Europe Regional Contest 2019 H. Ponk Warshall
    2019 ICPC Asia Yinchuan Regional G. Pot!!(线段树 区间更新 区间查询)
    CF1286A Garland
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14700098.html
Copyright © 2020-2023  润新知