F-Robots
题目
链接:https://ac.nowcoder.com/acm/contest/11259/F
来源:牛客网
题目大意:
有一些机器人在一个n×mn\times mn×m的矩阵中移动,现在有以下三种机器人:
1.只会向右的方向移动,每次从(x,y)到(x+1,y).
2.只会向下的方向移动,每次从(x,y)到(x,y+1).
3.即可以向右又可以向下移动.
现在给你一个大小为n×mn\times mn×m且只有字符0,1组成的矩阵,0表示可以走,然后有q组查询,每组查询会输入5个数字,分别为o,x1,y1,x2,y2,o代表机器人的类型,(x1,y1)是机器人的起点,(x2,y2)是机器人的终点,保证(x1,y1),(x2,y1)不为1.对每组样例,如果可以到达终点,输出yes,否则输出no.
思路
这题题面看起来很简单,但是数据范围很恶心,q能到达5×1055\times10^55×105.0≤n,m≤5×5000\le n,m \le 5\times 5000≤n,m≤5×500.即使给了我们5s的时间,采用每次搜索一次的方法也会超时.所以我们就要用到bitset来优化代码的时间复杂度.
对于前两种机器人判断能否到达终点的方法很简单,先判断两点的x或y是否相同,并在输入地图时计算每一行和每一列的前缀和就可以在O(1)的时间复杂度内判断了.
难点就在于第三种机器人.我们可以采用离线(即先输入所有询问)的方式来处理数据,这样可以减少相同起点的计算数.具体见代码.
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=510;
struct node{
int rx,ly,ry,id;
};
vector<node> p[N],t[N];
char mapp[N][N];
int x[N][N],y[N][N],n,m,q;
bool ans[500010];
bitset<N> vis[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf(" %c",&mapp[i][j]);
x[i][j]=x[i][j-1]+(mapp[i][j]=='1');
y[i][j]=y[i-1][j]+(mapp[i][j]=='1');
}
}
scanf("%d",&q);
for(int i=1;i<=q;i++){
int o,x1,y1,x2,y2;
scanf("%d%d%d%d%d",&o,&x1,&y1,&x2,&y2);
if(o==1){
if(y1==y2&&x2>=x1&&y[x2][y1]-y[x1-1][y1]==0) ans[i]=1;
}
else if(o==2){
if(x1==x2&&y2>=y1&&x[x1][y2]-x[x1][y1-1]==0)ans[i]=1;
}
else if(x1<=x2&&y1<=y2)p[x1].push_back(node{x2,y1,y2,i});
}
for(int l=1;l<=n;l++){
//将当前行上每个起点出发的询问,存储到终点的每行中
for(auto o:p[l])t[o.rx].push_back(o);
//初始化
//vis[x][y] 表示 (l,y) 能否走到 (?,x)
for(int i=1;i<=m;i++) vis[i].reset();
for(int i=1;i<=m;i++){
//若(l,i)有障碍物,清零
if(mapp[l][i]=='1') vis[i].reset();
//(l,i)无障碍物,标记(l,i) 可以走到 (l,i) ,合并上能走到 (l,i-1) 的起点方案
else vis[i][i]=1,vis[i]|=vis[i-1];
}
//枚举行
for(int r=l;r<=n;r++){
for(int i=1;i<=m;i++){
//走到 (r,i) 的方案,要合并上能走到 (r,i-1) 的方案
vis[i]|=vis[i-1];
//若 (r,i) 存在障碍物,则无方案
if(mapp[r][i]=='1')vis[i].reset();
}
for(auto o:t[r]){
ans[o.id]=vis[o.ry][o.ly];
}
t[r].clear();
}
}
for(int i=1;i<=q;i++){
if(ans[i])printf("yes\n");
else printf("no\n");
}
}
这篇博客主要介绍了如何解决一个关于机器人路径判断的编程竞赛题目。题目要求判断不同类型的机器人在给定的地图中能否从起点移动到终点。通过使用bitset优化,可以有效地降低时间复杂度,处理大量查询而不超时。对于只能向右或向下移动的机器人,可以通过计算行和列的前缀和快速判断;而对于可以向右和向下移动的机器人,采用离线处理并利用bitset更新行的状态,从而高效地确定能否到达终点。
325

被折叠的 条评论
为什么被折叠?



