这道题思路很简单,但是要把代码写得简洁,清晰,却不容易!
题解
直接模拟整个过程。走的时候记录走过的格子,最后检查总数是否等于总格子数-障碍数
模拟时用set加速查找过程
然而,本题有四个方向,我一开始就习惯性的四个方向分开讨论,于是写了100多行。调起来比较麻烦
最简单的写法是旋转矩阵(只要坐标对应旋转,相对位置是不变的,所以矩形内部的任何信息都没有发生变化)
然后就只考虑处理向右的情况
这种做法是在 @juniorcompressor 的代码中学到的
//需在C++17以上版本编译
#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
#define down(i,r,l) for (int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()
typedef long long ll;
typedef pair <int,int> pr;
const int maxn = 1e6 + 10;
vector <set<ll>> obstacles(4);
int n,m,k;
bool solve(){
ll num = (ll)n * m - k;
int l = 0 , r = m , u = 0 , d = n;
for (int i = 0; l < r and u < d ; i = (i + 1) % 4){
ll p = (ll)u * m + l;
auto it = obstacles[i].lower_bound(p);
int nxtr = (it == obstacles[i].end()) ? r : min((ll)r,*it - p + l);
num -= nxtr - l;
tie(l,r,u,d,n,m) = tuple(u + 1,d,m - nxtr,m - l,m,n); //旋转,注意当前的信息是和边界的相对位置。要把这个推清楚
}
//cout<<num<<endl;
return num == 0;
}
int main(){
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n>>m>>k;
rep(i,1,k){
int x,y;
cin>>x>>y; x--, y--;
for (auto &s : obstacles){ //建立四个方向的set,都是旋转到使得查询方向向右(每次逆时针转90度)
s.insert((ll)m * x + y);
tie(x,y,n,m) = tuple(m - 1 - y,x,m,n);
}
}
cout<<(solve() ? "Yes" : "No")<<"\n";
}
以前的分类讨论代码,巨长,且难调
#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
#define down(i,r,l) for (int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()
typedef long long ll;
typedef pair <int,int> pr;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
int n,m,k;
set <int> row[maxn],col[maxn];
ll sum;
//1 : right
//2 : down
//3 : left
//4 : up
int getR(set <int> &s,int p){
auto it = s.upper_bound(p);
assert(it != s.end());
return *it;
}
int getL(set <int> &s,int p){
auto it = s.lower_bound(p);
assert(it != s.begin());
return *(--it);
}
void solve(int x,int y,int dir,int U,int D,int L,int R){
//cout<<x<<" "<<y<<" "<<dir<<" "<<U<<" "<<D<<" "<<L<<" "<<R<<" "<<sum<<"\n";
if ( dir > 4 ) dir = 1;
if ( dir == 1 ){
int r = getR(row[x],y);
r = min(r - 1,R);
if ( r <= y ) return;
sum += r - y;
solve(x,r,2,U + 1,D,L,r);
}
if ( dir == 2 ){
int r = getR(col[y],x);
r = min(r - 1,D);
if ( r <= x ) return;
sum += r - x;
solve(r,y,3,U,r,L,R - 1);
}
if ( dir == 3 ){
int l = getL(row[x],y);
l = max(l + 1,L);
if ( l >= y ) return;
sum += y - l;
solve(x,l,4,U,D - 1,l,R);
}
if ( dir == 4 ){
int l = getL(col[y],x);
l = max(l + 1,U);
if ( l >= x ) return;
sum += x - l;
solve(l,y,1,l,D,L + 1,R);
}
}
int main(){
//freopen("input.txt","r",stdin);
ios::sync_with_stdio(false);
cin>>n>>m>>k;
int a[10][10];
rep(i,1,k){
int x,y;
cin>>x>>y;
row[x].insert(y);
col[y].insert(x);
//a[x][y] = 1;
}
/*rep(i,1,n){
rep(j,1,m){
cout<<a[i][j];
}
cout<<endl;
}*/
rep(i,1,n) row[i].insert(0) , row[i].insert(m + 1);
rep(i,1,m) col[i].insert(0) , col[i].insert(n + 1);
sum = 1;
solve(1,1,1,1,n,1,m);
if ( sum == (ll)n * m - k ) cout<<"Yes\n";
else{
sum = 1;
solve(1,1,2,1,n,1,m);
if ( sum == (ll)n * m - k ) cout<<"Yes\n";
else cout<<"No\n";
}
}