【搜索,Floodfill染色】Acwing2060 奶牛选美

原题链接
在这里插入图片描述
简而言之,就是求由X构成的两个集合之间的最短曼哈顿距离

#include<bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;

const int N = 55;
int n, m;
char g[N][N]; //存图
bool st[N][N]; //BFS的标记数组
int dx[]={-1, 0, 1, 0}, dy[]={0, 1, 0, -1};
// a存放第一个集合中所有点的坐标
// b存放第二个集合中所有点的坐标
vector<PII> a, b;

//寻找两个斑点,并进行着色
void bfs(int x, int y, int k)
{
    queue<PII> q;
    if(!k) a.push_back({x, y}); //如果k为0,则加入到a中
    else b.push_back({x, y});//否则加入到b中
    
    q.push({x, y}); // vector中用的是push_back(),queue中直接push就行了
    st[x][y] = true;
    
    while(q.size())
    {
        PII t = q.front();
        q.pop();
        int sx = t.first, sy = t.second;
        for(int i=0; i<4; i++)
        {
            int nx = sx+dx[i], ny = sy + dy[i];
            if(nx >=0 && nx<n && ny>=0 && ny <m &&g[nx][ny] == 'X' && !st[nx][ny])
            {
                q.push({nx, ny});
                if(!k) a.push_back({nx, ny});
                else b.push_back({nx, ny}); //k就是一个标记,用于区分两个斑点
                
                st[nx][ny] = true;
            }
        }
    }
    
}

//求两个点之间的曼哈顿距离
int get(int x1, int y1, int x2, int y2)
{
    return abs(x1 - x2) + abs(y1 - y2);    
}

int main()
{
    cin >> n >> m;
    for(int i=0; i<n; i++) cin>>g[i]; //每次读入一行
    // t做标记,染色时候,判断在哪个集合
    int t=0;
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            if(g[i][j] == 'X' && !st[i][j])
            {
                bfs(i, j, t);
                // 如果从上一条语句中退出了
                // 那么再次进入BFS进行着色的时候
                // 一定进的是不同的X的集合了
                // 否则就不会出来,所以t需要置为1
                t = 1;
            }
    
    int res = 1e9;
    for(int i=0; i<a.size(); i++)
        for(int j=0; j<b.size(); j++)
        {
            res = min(res, get(a[i].first, a[i].second, b[j].first, b[j].second));
        }
    
    cout<<res-1<<endl;
    
    return 0;
}
DFS做法:参考链接

数据范围很小,可以DFS求出两块斑点内的所有点然后比较。复杂度为 O(nm)

#include <iostream>
#include <vector>
using namespace std;
using T = pair<int, int>;

const int N = 60;

const int dr[] = { -1, 0, 1, 0 }, dc[] = { 0, 1, 0, -1 };

int n, m;
char g[N][N];
bool st[N][N];
vector<T> block[2];

void dfs (vector<T> & block, int x, int y)
{
    st[x][y] = true;
    block.push_back({x, y});
    for (int i = 0; i < 4; i ++ )
    {
        int dx = x + dr[i], dy = y + dc[i];
        if (st[dx][dy] || dx < 1 || dx > n || dy < 1 || dy > m || g[dx][dy] != 'X') continue;
        dfs(block, dx, dy);
    }
}

int main ()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) cin >> (g[i] + 1);

    for (int i = 1, which = 0; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            if (!st[i][j] && g[i][j] == 'X') dfs(block[which ++], i, j);

    int dist = 1e9 + 10;
    for (T & a : block[0])
        for (T & b : block[1])
            dist = min(abs(a.first - b.first) + abs(a.second - b.second), dist);

    cout << dist - 1 << endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值