Codeforces 1301F Super Jaber

Codeforces 1301F Super Jaber

题目链接

https://codeforces.com/contest/1301/problem/F

题目大意

一个 $n \times m$ 的网格,每个格子有一个颜色,颜色的总数不超过 $40$ 个。从一个格子出发可以花 $1$ 单位的时间到达与它有边相邻的格子或者颜色相同的格子。 $q$ 次询问,每次询问两个格子之间的最短路。

题目分析

如果询问的两点的最短路径使用了颜色跳跃的话,那么显然答案可以表示为两个点分别到达该颜色的最短路加 $1$。如果不跳跃的话显然答案是两个格子之间的曼哈顿距离。那么可以用 $BFS$ 求出所有的点到达某种颜色的最小值,即可解决这道题。

代码

#include <bits/stdc++.h>

using namespace std;

const int inf = 0x3f3f3f3f;

int dis[1005][1005][45];
int a[1005][1005];

bool v[45][45];

struct ex {
	int x, y, z;
};

vector <ex> vec[45];

queue <ex> q;

int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};

int n, m, k, t;

int main(){
	int i, j;
	
	scanf("%d%d%d", &n, &m, &k);
	
	memset(dis, 0x3f3f3f3f, sizeof(dis));
	
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			scanf("%d", &a[i][j]);
			vec[a[i][j]].push_back({i, j});
		}
	}
	for(i=1;i<=k;i++) v[i][i] = true;
	
	for(int z=1;z<=k;z++){
		for(i=1;i<=n;i++){
			for(j=1;j<=m;j++){
				if(a[i][j] == z){
					dis[i][j][z] = 0;
					q.push({i, j});
				}
			}
		}
		while(q.size()){
			int x = q.front().x, y = q.front().y;
			q.pop(); 
			
			for(i=0;i<4;i++){
				if(1 <= x + dx[i] and x + dx[i] <= n and 1 <= y + dy[i] and y + dy[i] <= m){
					if(dis[x + dx[i]][y + dy[i]][z] > dis[x][y][z] + 1){
						dis[x + dx[i]][y + dy[i]][z] = dis[x][y][z] + 1;
						q.push({x + dx[i], y + dy[i], z});
					}
				}
			}
			
			if(!v[z][a[x][y]]){
				v[z][a[x][y]] = true;
				for(auto tmp : vec[a[x][y]]){
					if(dis[tmp.x][tmp.y][z] > dis[x][y][z] + 1){
						dis[tmp.x][tmp.y][z] = dis[x][y][z] + 1;
						q.push({tmp.x, tmp.y, z});
					}
				}
			}
		}
	}
	
	scanf("%d", &t);
	
	while(t--){
		int x, y, a, b;
		scanf("%d%d%d%d", &x, &y, &a, &b);
		int ans = abs(x - a) + abs(y - b);
		for(i=1;i<=k;i++){
			ans = min(ans, dis[x][y][i] + dis[a][b][i] + 1);
		}
		printf("%d\n", ans);
	}
	
	return 0;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据