Codeforces 1301F Super Jaber (多源bfs)
题意
1e3*1e3的网格,每个格子有一种颜色,共有40种颜色,每个格子可以上下左右走,相同颜色的格子可以一步传送到
1e5组询问,每次给你起点和终点st,问你最少几步走到
思路
如果不使用传送,答案就是曼哈顿距离
否则的话我们可以枚举中间传送的那种颜色i,答案就是(s到颜色i的最短路)+(y到颜色i的最短路)+1
这里的最短路是可以使用传送的,这个可以用多源bfs预处理出来
代码
为什么我的程序比别人慢这么多?
UPD:找到原因了,定义的数组改为c[41][1001][1001]就能快两秒。。可是为啥呢
int n,m,k;
int a[1111][1111];
bool ck(int x, int y){
return x>=1&&x<=n&&y>=1&&y<=m;
}
int dx[5]={0,1,0,-1};
int dy[5]={1,0,-1,0};
int vis[44];
int c[1001][1001][41];
vector<PI>v[44];
#define eb emplace_back
#define mp make_pair
queue<PI>q;
void bfs(int i){
mem(vis,0);
for(int j = 0; j < (int)v[i].size(); j++){
q.push(v[i][j]);
c[v[i][j].fst][v[i][j].sc][i]=0;
}
while(!q.empty()){
auto top = q.front();
q.pop();
int x = top.fst;
int y = top.sc;
int w = c[x][y][i];
for(int j = 0; j < 4; j++){
int tox = x+dx[j];
int toy = y+dy[j];
if(ck(tox,toy)&&c[tox][toy][i]==-1){
c[tox][toy][i]=w+1;
q.push(mp(tox,toy));
}
}
if(!vis[a[x][y]]){
vis[a[x][y]]=1;
for(int j = 0; j <(int)v[a[x][y]].size(); j++){
int tox = v[a[x][y]][j].fst;
int toy = v[a[x][y]][j].sc;
if(c[tox][toy][i]==-1){
c[tox][toy][i]=w+1;
q.push(mp(tox,toy));
}
}
}
}
}
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]);
v[a[i][j]].pb(mp(i,j));
}
}
mem(c,-1);
for(int i = 1; i <= k; i++){
bfs(i);
}
int Q;
scanf("%d", &Q);
while(Q--){
int x1,y1,x2,y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
int ans = abs(x1-x2)+abs(y1-y2);
for(int i = 1; i <= k; i++){
ans=min(ans,c[x1][y1][i]+c[x2][y2][i]+1);
}
printf("%d\n",ans);
}
return 0;
}