[CF1236D] Alice and the Doll
Description
\(N \times M\)网格,有 \(K\) 个格子里有障碍物。每次经过一个格子的时候只能直走或者右转一次。初态在 \((1,1)\) 格子向上。求是否存在一条路径经过所有无障碍格子恰好一次。
Solution
最优的走法是遇到障碍或者边界就右转,否则直走。
走过一排格子相当于挪动边界线。
这两个结论仔细品味起来很挺有深度的。
然后暴力模拟就可以了,找障碍物的过程可以用 set 优化。
这题的坐标系好像有点奇怪,SB的我就这么搞反坐标WA了一发。然后忘记开longlong又WA了一发。
Code
#include <bits/stdc++.h> using namespace std; #define int long long const int N = 100005; int n,m,k,t1,t2,t3,t4,lx,ly,ux,uy,dir,ans=1; set <int> sx[N],sy[N]; int FindIncX(int x,int y) { return min(ux,*sy[y].lower_bound(x)); } int FindDecX(int x,int y) { return max(lx,*(--sy[y].lower_bound(x))); } int FindIncY(int x,int y) { return min(uy,*sx[x].lower_bound(y)); } int FindDecY(int x,int y) { return max(ly,*(--sx[x].lower_bound(y))); } signed main() { cin>>n>>m>>k; lx=0; ly=0; ux=n+1; uy=m+1; for(int i=1; i<=m; i++) { sy[i].insert(0); sy[i].insert(n+1); } for(int i=1; i<=n; i++) { sx[i].insert(0); sx[i].insert(m+1); } for(int i=1; i<=k; i++) { cin>>t1>>t2; sx[t1].insert(t2); sy[t2].insert(t1); } dir=0; int x=1,y=1; while(true) { int nx,ny; switch(dir) { case 0: nx=x; ny=FindIncY(x,y)-1; break; case 1: ny=y; nx=FindIncX(x,y)-1; break; case 2: nx=x; ny=FindDecY(x,y)+1; break; case 3: ny=y; nx=FindDecX(x,y)+1; break; } if(x==nx && y==ny) { dir=(dir+1)%4; switch(dir) { case 0: nx=x; ny=FindIncY(x,y)-1; break; case 1: ny=y; nx=FindIncX(x,y)-1; break; case 2: nx=x; ny=FindDecY(x,y)+1; break; case 3: ny=y; nx=FindDecX(x,y)+1; break; } if(x==nx && y==ny) break; } ans += abs(nx-x) + abs(ny-y); switch(dir) { case 0: lx=max(lx,nx); break; case 1: uy=min(uy,ny); break; case 2: ux=min(ux,nx); break; case 3: ly=max(ly,ny); break; } x=nx; y=ny; } //cout<<ans<<endl; if(ans==n*m-k) { cout<<"Yes"<<endl; } else { cout<<"No"<<endl; } }