题意:给定一个 n × m 的矩阵,矩阵中有些地方有障碍,一共 k 个障碍,问从坐标 (1,1) 开始,朝向 y 轴,每一次在一个点上至多只能右转一次的情况下,能不能把矩阵中所有没有障碍的点走完(障碍点不能走,点不能重复走);
分析: 这题的条件就相当于让你蛇形走位,看能不能把所有能走的点走完,所以从开始每个方向上走到能走的最远点(边界或者前面有障碍挡着),然后再转一次向;
代码:
#include<set>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 1E5+5;
set<int>R[N];
set<int>C[N];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
R[x].insert(y);
C[y].insert(x);
}
for(int i=1;i<=n;i++)
{
R[i].insert(0);
R[i].insert(m+1);
}
for(int i=1;i<=m;i++)
{
C[i].insert(0);
C[i].insert(n+1);
}
int dn_x=1,dn_y=1,up_x=n,up_y=m;
int dir=0,x=1,y=1;
ll ans=0; int fir=1;
while(1)
{
if(dir==0)
{
int yy = *R[x].lower_bound(y)-1;
yy=min(yy,up_y);
if(yy==y&&(!fir)) break; //fir是为了避免m=1的极端情况
dn_x=x+1;
ans+=yy-y;
y=yy;
}
if(dir==1)
{
int xx = *C[y].lower_bound(x)-1;
xx=min(xx,up_x);
if(xx==x) break;
up_y=y-1;
ans+=xx-x;
x=xx;
}
if(dir==2)
{
int yy = *(--R[x].lower_bound(y))+1;
yy=max(yy,dn_y);
if(y==yy) break;
up_x=x-1;
ans+=y-yy;
y=yy;
}
if(dir==3)
{
int xx= *(--C[y].lower_bound(x))+1;
xx=max(xx,dn_x);
if(x==xx) break;
dn_y=y+1;
ans+=x-xx;
x=xx;
}
fir=0;
dir=(dir+1)%4;
}
if((ll)ans+k+1==(ll)n*m) puts("Yes");
else puts("No");
}