习题:Three States(bfs)

题目

传送门

思路

这题的主要难点在于我们不知道是三个起点分别在哪里

但是我们知道三条路径一定会交于某一个点

基于此,我们考虑枚举这一个点,

那么算法的复杂度就卡在这个点和三个王国的国土的最短路径上面

这个可以用bfs来预处理,\(dis[k][i][j]\)第k个王国距离点\((i,j)\)的最短距离

我们只需要考虑经过的是国土还是公有土地即可

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define x first
#define y second
struct node
{
    pair<int,int> x;
    long long step;
};
int n,m;
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
char a[1005][1005];
long long dis[4][1005][1005],ans=(1<<30);
deque<node> q;
bool inside(int x,int y)
{
    if(1<=x&&x<=n&&1<=y&&y<=m)
        return 1;
    return 0;
}
void bfs(int col)
{
    while(!q.empty())
        q.pop_front();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(a[i][j]=='0'+col)
            {
                dis[col][i][j]=0;
                q.push_back((node){make_pair(i,j),0});
            }
    while(!q.empty())
    {
        node t=q.front();
        q.pop_front();
        t.step=dis[col][t.x.x][t.x.y];
        for(int i=1;i<=4;i++)
        {
            int tx=t.x.x+dx[i];
            int ty=t.x.y+dy[i];
            if(inside(tx,ty)&&a[tx][ty]!='#')
            {
                int cost=0;
                if(a[tx][ty]=='.')
                    cost++;
                if(t.step+cost<dis[col][tx][ty])
                {
                    dis[col][tx][ty]=t.step+cost;
                    if(cost)
                        q.push_back((node){make_pair(tx,ty),t.step+cost});
                    else
                        q.push_front((node){make_pair(tx,ty),t.step+cost});
                }
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>a[i][j];
    for(int k=1;k<=3;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                dis[k][i][j]=(1ll<<30);
    for(int i=1;i<=3;i++)
        bfs(i);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='#')
                continue;
            long long val=0;
            for(int k=1;k<=3;k++)
                val+=dis[k][i][j];
            if(a[i][j]=='.')
                ans=min(ans,val-2);
            else
                ans=min(ans,val);
        }
	}
    if(ans>(1ll<<25))
        cout<<"-1";
    else
        cout<<ans;

    return 0;
}
上一篇:PTA练习题:公路村村通


下一篇:equals()和hashCode()隐式调用时的约定