zoukankan      html  css  js  c++  java
  • CF1301F Super Jaber

    题面

    最终答案的方案可以分为2种:1、不使用传送 2、从起点s到最近(步数最少)的颜色为c的格子x,传送到离终点t最近的颜色也为c的格子y,再走到t(从s到x,y到t的过程中均可使用传送)

    询问次数多,如果预处理出f[k][i][j]表示从格子(i, j)到一个颜色为k的格子的最少步数,询问时只要枚举中间格子的颜色取最小值即可得出答案

    关键在于预处理的方法喽

    把每种颜色分开处理(对f数组的每个k处理一遍),如果在上述过程中,从s到x,y到t的过程中不能使用传送,普通的多源bfs即可解决问题

    处理中间过程的传送方法也简单:对于每一种颜色color,多源bfs的过程中第一次走到颜色为color的格子上时,将所有颜色为color且未被访问的格子都放入队列

    每次多源bfs中每个格子只访问一遍,复杂度O(n),预处理总复杂度O(nk),询问复杂度O(mk),总复杂度O((n+m)k)

    #include <bits/stdc++.h>
    using namespace std;
    inline void read (int &x) {
        char ch = getchar(); x = 0;
        while (!isdigit(ch)) ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
    } const int N = 1024, K = 50;
    int n, m, k, a[N][N], f[K][N][N];
    int sx[4] = {0, 1, 0, -1}, sy[4] = {1, 0, -1, 0};
    vector <pair<int, int> > v[K];
    queue <pair<int, int> > que[K]; int used[K], vis[N][N];
    inline void work (int p) {
        for (int i = 1; i <= k; ++i) used[i] = 0;
        while (que[p].size()) {
            int x = que[p].front().first, y = que[p].front().second;
            for (int i = 0; i < 4; ++i) {
                int tx = x + sx[i], ty = y + sy[i];;
                if (tx < 1 || ty < 1 || tx > n || ty > m || f[p][tx][ty]) continue;
                f[p][tx][ty] = f[p][x][y] + 1; que[p].push (make_pair (tx, ty));
            } if (!used[a[x][y]]) {
                used[a[x][y]] = 1;
                for (int i = 0; i < v[a[x][y]].size(); ++i) {
                    int tx = v[a[x][y]][i].first, ty = v[a[x][y]][i].second;
                    if (!f[p][tx][ty]) f[p][tx][ty] = f[p][x][y] + 1, que[p].push (make_pair (tx, ty));
                }
            } que[p].pop();
        }
    }
    #define Min(x, y) (x > y ? y : x)
    signed main() {
        read (n), read (m), read (k);
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j) {
                read (a[i][j]), f[a[i][j]][i][j] = 1;
                v[a[i][j]].push_back (make_pair (i, j)), que[a[i][j]].push (make_pair (i, j));
            }
        for (int i = 1; i <= 40; ++i) work (i);
        int T, xi, yi, xj, yj; read (T);
        while (T--) {
            read (xi), read (yi), read (xj), read (yj);
            int res = abs (xi - xj) + abs (yi - yj);
            for (int i = 1; i <= k; ++i) res = Min (res, f[i][xi][yi] + f[i][xj][yj] - 1);
            printf ("%d
    ", res);
        } return 0;
    }
    
  • 相关阅读:
    Javascript 跨域知识详细介绍
    jquery对象和DOM对象的相互转换详解
    jQuery 第四章 实例方法 DOM操作之data方法
    jQuery 第四章 实例方法 DOM操作_基于jQuery对象增删改查相关方法
    jQuery 第二章 实例方法 DOM操作取赋值相关方法
    jQuery 第三章 CSS操作
    jQuery 第二章 实例方法 DOM操作选择元素相关方法
    jQuery 第一章 $()选择器
    javaScript之实战 页面筛选功能
    javaScript 二分查找
  • 原文地址:https://www.cnblogs.com/whx666/p/12674631.html
Copyright © 2011-2022 走看看