Atcoder AGC043A Range Flip Find Route 题解 [ 绿 ] [ 01 BFS ] [ 观察 ]

Range Flip Find Route:牛逼 01 BFS 题,被诈骗了。

观察

直接观察怎么去选矩形是没有用的,我们考虑先钦定好一条路线,然后再看怎么最小化操作次数。

显然,这一条路线一定是一些拐点组成的,只可能向右、向下移动,并且是一段路、一段墙组合而成的。于是我们就有一个很显然的贪心思路:每次选择路线上连续的一段墙删掉。这段墙一定能被覆盖,因为路线只能向右向下,所以我们从一段墙的最后一堵墙向前找,找到第一堵墙,把这个矩形内的格子取反即可。容易发现这样即使影响到矩形内非所选路线的格子,也不会使所选路线受到影响

所以原题就转化为了:让你求一条路线,使得路线上连续的墙的段数最少。

BFS

这个就很容易做了,要么就是先找出所有连通块,缩点之后跑 BFS;要么就是在原位置是道路,移动后位置是墙的边上权值赋为 \(1\),其他赋值为 \(0\),跑 01 BFS 即可。

时间复杂度 \(O(nm)\),代码采用了 01 BFS 的方法,注意一个点可能被更新多次,不能入队一次之后就不入队了。

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const int N=1005;
int gox[]={0,1};
int goy[]={1,0};
int n,m,d[N][N];
char c[N][N];
bool legal(int x,int y)
{
    return (x>=1&&x<=n&&y>=1&&y<=m);
}
void bfs()
{
    memset(d,0x3f,sizeof(d));
    d[1][1]=(c[1][1]=='#');
    deque<pi>q;
    q.push_back({1,1});
    while(!q.empty())
    {
        pi u=q.front();
        q.pop_front();
        int nx=u.fi,ny=u.se;
        for(int i=0;i<2;i++)
        {
            int tx=nx+gox[i],ty=ny+goy[i];
            if(!legal(tx,ty))continue;
            int w=(c[nx][ny]=='.'&&c[tx][ty]=='#');
            if(d[tx][ty]>d[nx][ny]+w)
            {
                d[tx][ty]=d[nx][ny]+w;
                if(w)q.push_back({tx,ty});
                else q.push_front({tx,ty});
            }
        }
    }
    cout<<d[n][m];
}
int main()
{
    //freopen("sample.in","r",stdin);
    //freopen("sample.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>c[i][j];
    bfs();
    return 0;
}
posted @ 2025-03-09 15:07  KS_Fszha  阅读(26)  评论(0)    收藏  举报