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;
}

浙公网安备 33010602011771号