F. Super Jaber (多源BFS)

题目:传送门

题意: 有n * m个城市,每个城市都有一个颜色,共有 k 种颜色,也就是每个城市的颜色只能是 1 ~ k 的某个数字。

       然后,有q次询问,每次询问给你 x1, y1, x2, y2;问你从(x1, y1)到(x2, y2)的最少操作数。

       操作有两种: 1、 你可以移动到你当前位置的上下左右,只要不越界。

              2、你可以移动到任意和你当前所在的位置颜色相同的位置。

   1 <= n, m <= 1000,  k <= min(40, n * m);

题解: 多源dfs, dis[ col ][ i ][ j ] 表示颜色为 col 的点 到 (i, j) 这个点的最少操作。

   

#include <bits/stdc++.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
#define PI acos(-1)
using namespace std;

const int N = 510;

int n, m, k;
vector < pair<int, int> > G[50];
int dis[50][1005][1005], vis[50];
queue < pair<int, int> > Q;
int xx[4] = {0, 0, -1, 1};
int yy[4] = {1, -1, 0, 0};
int a[1005][1005];

void bfs(int col) {
    for(pair<int, int> v : G[col]) {
        dis[col][v.first][v.second] = 0;
        Q.push(v);
    }
    rep(i, 1, k) vis[i] = 0;
    while(!Q.empty()) {
        pair <int ,int> tmp = Q.front(); Q.pop();
        int x = tmp.first, y = tmp.second;
        rep(i, 0, 3) {
            int nx = x + xx[i];
            int ny = y + yy[i];
            if(nx < 1 || nx > n || ny < 1 || ny > m || dis[col][nx][ny] != -1) continue;
            dis[col][nx][ny] = dis[col][x][y] + 1;
            Q.push(make(nx, ny));
        }
        if(!vis[a[x][y]]) {
            vis[a[x][y]] = 1;
            for(pair <int, int> v : G[a[x][y]]) {
                if(dis[col][v.first][v.second] == -1) {
                    dis[col][v.first][v.second] = dis[col][x][y] + 1;
                    Q.push(v);
                }
            }
        }
    }
}
int main() {
    scanf("%d %d %d", &n, &m, &k);
    rep(i, 1, n) rep(j, 1, m) scanf("%d", &a[i][j]), G[a[i][j]].pb(make(i, j));
    mem(dis, -1);
    rep(i, 1, k) bfs(i);
    int q; scanf("%d", &q);
    while(q--) {
        int x1, x2, y1, y2;
        scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
        int ans = abs(y1 - y2) + abs(x2 - x1);
        rep(i, 1, k) ans = min(ans, dis[i][x1][y1] + dis[i][x2][y2] + 1);
        printf("%d\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Willems/p/12308289.html

时间: 2024-10-08 11:00:12

F. Super Jaber (多源BFS)的相关文章

CF 986A Fair——多源bfs

题目:http://codeforces.com/contest/986/problem/A 此题乍一看没什么不T的思路... 发现边权是1,bfs? 考虑朴素的想法,遍历所有的点,bfs,过程中更新出各种商品的最短路,然后排序加和-- 好像很不行,似乎有一大堆冗余的东西,主要因为每个点上只有一种商品啊: 不妨干脆换个思路,不是找每个点到每种商品的距离,而是找每种商品到每个点的距离,如何? 一种商品存在于多个点上,可以进行多源 bfs! 也就是 bfs 一开始的时候把多个点加进优先队列里,复杂度

bzoj 2252 [ 2010 Beijing wc ] 矩阵距离 —— 多源bfs

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2252 又没能自己想出来... 一直在想如何从每个1开始广搜更新答案,再剪剪枝,什么遇到1就不走了... 然而实际上直接多源bfs,从所有1一起开始,因为只需要找到0碰到的第一个1即可: 这样搜一遍就可以,复杂度很美. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<al

多源bfs

https://codeforces.com/contest/1283/problem/D 题意:在一条无限长的坐标轴上,给你n颗树,m个人.求所有人到树的最短距离的总和和坐标. 解法:多源bfs,map标记. //#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iost

uva 11624 Fire!(多源BFS)

uva 11624 Fire! 题目大意:J在迷宫里工作,有一天迷宫起火了,火源有多处.每过一秒,火源都会向四个方向蔓延,J也会向四个方向移动,问J能不能跑出去,能的话输出他跑出去的最短时间,否则输出"IMPOSSIBLE" 解题思路:先进行一次BFS,找出每一点火焰蔓延到该处的最短时间.然后根据这张"火势图",对J的行进路线进行BFS.注意J在边缘的时候,以及没有火源的时候. #include <cstdio> #include <cstring

Codeforces Round #619 (Div. 2)

A. Three Strings 题意:给三个长度相同的非空字符串abc,依次将c中的每个字符和a或者b中对应位置的字符进行交换,交换必须进行,问能否使得ab相同. 思路:对于每一个位置,如果三个字符都不相同,那一定不同,如果有两个相同且不是ab相同,则合法,否则不合法,如果三个字符都相同,那么合法. 1 #include<bits/stdc++.h> 2 #define LL long long 3 #define dl double 4 void rd(int &x){ 5 x=0

关于Python的super用法研究

一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在python 2.2以前,通常的写法如代码段1: 代码段1: class A:  def __init__(self):   print "enter A"   print "leave A" class B(A):  def __init__(self):   print "enter B"   A.__init__(self)   print "

Android Scroller源码解析

1. 前言 通过view本身提供的scrollTo/scrollBy方法实现滑动,其过程是瞬间的,想要实现弹性滑动的时候,需要用scroller来实现.Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context).mScroller本身,并不会导致View的滚动,通常是用mScroller记录/计算View滚动的位置,需要重写View的computeS

有上下界的、有多组源汇的、网络流、费用流问题

先默认读者有基础的网络流以及费用流的知识前置 1.有上下界无源点汇点的可行流问题: 在本文中指: 原图中没有任何一个点可以凭空产生流量,亦没有任何一个点可以凭空消灭流量: 存在边既有流量上界又有流量下界: 求每条边流量的一组可行解: 满足每个点的入流量等于出流量: 由题意可见本题的图中有环,于是此类问题也被称作循环流: 这里给出的解法是将本题转换为一道普通的有上界最大流问题: 修改本题原图中每条边的流量下界为0,上界为原上界-原下界: 视为该边现在已经拥有了等同于该边流量下界的基础流量了, 然而

python super()

一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1: 代码段1: class A: def __init__(self): print "enter A" print "leave A" class B(A): def __init__(self): print "enter B" A.__init__(self) print "leave B"