Codeforces 1301 F. Super Jaber —— bfs,思维

16 篇文章 0 订阅

This way

题意:

现在有一张n*m的矩形图,每个格子有一个颜色,并且每个格子都可以花一秒的时间往周围四格扩散或者跳到另一个相同颜色的位置。每次问你从(x1,y1)跳到(x2,y2)至少要花多少时间

题解:

首先如果直接走是最短的那么就直接走,否则就一定至少会在一个颜色进行跳转。
dis[c][i][j]表示从颜色c跳到位置(i,j)的最少时间
那么直接进行bfs,首先如果这个颜色没跳过,就进行跳转,否则就往旁边进行扩散即可。

#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
const int N=1e3+5,M=45;
int dis[M][N][N],mp[N][N],n,m,q,k;
queue<pa>Q;
int xmov[]={1,0,-1,0};
int ymov[]={0,1,0,-1};
int cal[M];
void bfs(int c){
    memset(cal,0,sizeof(cal));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]==c)
                Q.push({i,j});
    while(!Q.empty()){
        int x=Q.front().first,y=Q.front().second;Q.pop();
        if(!cal[mp[x][y]]&&mp[x][y]!=c){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(i==x&&j==y)continue;
                    if(mp[i][j]==mp[x][y]&&!dis[c][i][j])
                        dis[c][i][j]=dis[c][x][y]+1,Q.push({i,j});
                }
            }
            cal[mp[x][y]]=1;
        }
        for(int i=0;i<4;i++){
            int nx=x+xmov[i],ny=y+ymov[i];
            if(nx<1||nx>n||ny<1||ny>m||dis[c][nx][ny]||mp[nx][ny]==c)continue;
            dis[c][nx][ny]=dis[c][x][y]+1;
            Q.push({nx,ny});
        }
    }
}
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",&mp[i][j]);
    for(int i=1;i<=k;i++)
        bfs(i);
    scanf("%d",&q);
    while(q--){
        int x1,x2,y1,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        int ans=abs(x1-x2)+abs(y1-y2);
        //if(mp[x1][y1]==mp[x2][y2])ans=1;
        if(x1==x2&&y1==y2)ans=0;
        for(int i=1;i<=k;i++)
            ans=min(ans,dis[i][x1][y1]+dis[i][x2][y2]+1);
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值