Super Jaber
题意:有N*M的一个网格图,每一个格子都是代表一个点,每个点都有自己的颜色,每个点都可以走到邻近的某个点,也可以是直接利用跳转,跳转到颜色相同的点,现在,给出Q组询问,我们想知道从(sx,sy)到(ex,ey)的最短路有多长。
思路:因为这里的颜色数很少,所以很容易想到是跳颜色这样一个做法,如果说不跳颜色的话,那么就是二者的曼哈顿距离了,这肯定是可以O(1)计算得到的,接下去考虑的肯定就是需要跳转这样的一个做法了,因为颜色足够的少,所以我们不妨从颜色角度来考虑,考虑以中间哪个颜色作为跳板。
既然要用中间的某个颜色作为跳板的话,那么,这个颜色肯定是跳了的,那么就是需要知道的是这个颜色到其余各点的距离了,这个可以通过O(K*N*M)的BFS搜索来求得。中间需要剪枝,每个其余的颜色都是只能作为跳板一次,因为不可避免的是有时候的最短路,得从中间做一个跳板,但是每个颜色最多使用一次,这里需要剪枝,不然就会像我一样TLE on TEST 9。
那么,这样做的正确性来源于哪里呢?首先不需要任何跳板,我们直接走曼哈顿距离的正确性显而易见,其次就是需要跳板的时候了,既然需要跳板,那么就是dis[col][sx][sy] + dis[col][ex][ey] + 1。有些col点并没有跳,甚至有些col点要是跳的话反而更远了,但是别忘了我们这里的查的部分是“必须有跳的”,那么K种颜色中必定是有一个颜色作为了这个跳板,并且还是最短路径上的一个必经之路,于是,这里的正确性就显现出来了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
#define MIN(a, b) a > b ? b : a
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int dir[4][2] =
{
-1, 0,
0, -1,
1, 0,
0, 1
};
int N, M, K, a[1005][1005], Ques;
inline bool In_Map(int x, int y) { return x >= 1 && y >= 1 && x <= N && y <= M; }
vector<pair<int, int>> col[45];
bool vis_col[45], vis_point[1005][1005];
short int dis[45][1005][1005];
queue<pair<int, int>> Q;
pair<int, int> now;
inline void bfs(int id)
{
for(int i=1; i<=N; i++) for(int j=1; j<=M; j++) { dis[id][i][j] = 2020; vis_point[i][j] = false; }
for(int i=1; i<=K; i++) vis_col[i] = false;
int len = (int)col[id].size(); vis_col[id] = true;
for(int i=0, x, y; i<len; i++)
{
x = col[id][i].first; y = col[id][i].second;
dis[id][x][y] = 0;
vis_point[x][y] = true;
Q.push(MP(x, y));
}
int x, y, xx, yy;
while(!Q.empty())
{
now = Q.front(); Q.pop();
x = now.first; y = now.second;
if(!vis_col[a[x][y]])
{
vis_col[a[x][y]] = true;
len = (int)col[a[x][y]].size();
for(int i=0; i<len; i++)
{
xx = col[a[x][y]][i].first; yy = col[a[x][y]][i].second;
if(vis_point[xx][yy]) continue;
vis_point[xx][yy] = true;
dis[id][xx][yy] = dis[id][x][y] + 1;
Q.push(MP(xx, yy));
}
}
for(int i=0; i<4; i++)
{
xx = x + dir[i][0]; yy = y + dir[i][1];
if(!In_Map(xx, yy) || vis_point[xx][yy]) continue;
vis_point[xx][yy] = true;
dis[id][xx][yy] = dis[id][x][y] + 1;
Q.push(MP(xx, yy));
}
}
}
int main()
{
scanf("%d%d%d", &N, &M, &K);
for(int i=1; i<=N; i++) for(int j=1; j<=M; j++) { scanf("%d", &a[i][j]); col[a[i][j]].push_back(MP(i, j)); }
for(int i=1; i<=K; i++) bfs(i);
short int sx, sy, ex, ey, ans;
scanf("%d", &Ques);
while(Ques--)
{
scanf("%hd%hd%hd%hd", &sx, &sy, &ex, &ey);
ans = abs(sx - ex) + abs(sy - ey);
for(int i=1; i<=K; i++) ans = MIN(ans, dis[i][sx][sy] + dis[i][ex][ey] + 1);
printf("%hd\n", ans);
}
return 0;
}
![点击并拖拽以移动 wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==](https://i-blog.csdnimg.cn/blog_migrate/1e4abe4d1d784936886d4fe9ded67ccf.gif)