题解 P1299 【切孔机】
难度刷上来的吧。。。其实应该向xzz大佬学习:评入门啊
AC里面一堆打表的。。。https://www.luogu.org/record/show?rid=4916843 这个提交记录就是把n全部打出来,然后根据n打表。。然后除了我之外两个没用打表的大佬代码出奇的一致。。。
我还是来讲讲正确的做法吧。
首先要理解鬼畜的题意,连在一起的都只能算一个。
那么显然第一想法就是搜索。
首先先把除了洞以外的点遍历一遍,遇到墙就不要去。
然后对于找洞我们就要先判断出哪些点可以去哪些不可以,分类讨论。
1.
对于我用红笔圈着的那个点,即两个矩阵的相点不能去。还有把图倒过来,两个矩阵的交点不能去。
2.
我圈的的这一排点也是不能去的。把图逆时针旋转90°的那些点也不能去。
3.
我圈的的这一排点也是能去的。把图逆时针旋转90°的那些点也能去。
4. 除上面这些特殊点外的普通点,能不能去就是我们遍历时有没有去这些点
然后在能跑的洞一个一个遍历下就行了。
注意起点和终点在同一个点的地方不是一个洞。
代码:
#include<cstdio>
#include<algorithm>
#include<string>
#include<queue>
#include<set>
#include<vector>
#include<map>
#define For(i,x,y) for (int i=(x);i<=(y);i++)
#define Dow(i,x,y) for (int i=(x);i>=(y);i--)
#define cross(i,k) for (int i=first[k];i;i=last[i])
#define il inline
#define vd void
#define ll long long
#define N 110
#define maxn 2010
using namespace std;
il int read(){
int x=0;int ch=getchar(),f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
if (ch=='-'){f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int dx[4]={0,-1,0,1};
const int dy[4]={-1,0,1,0};
int n,h,t,x1,y1,x2,y2,ans,l[maxn*maxn],r[maxn*maxn];
bool mp[maxn][maxn],vis[maxn][maxn],b[maxn][maxn];
il int max(int x,int y){return x>y?x:y;}
il int min(int x,int y){return x<y?x:y;}
il vd bfs(){
int h=0,t=1,i,j;
l[1]=0,r[1]=0;
vis[l[1]][r[1]]=1;
while (h<t){
h++;
For(k,0,3){
i=l[h]+dx[k],j=r[h]+dy[k];
if (i<0||j<0||i>2001||j>2001) continue;
if (mp[i][j]||vis[i][j]) continue;
l[++t]=i,r[t]=j,vis[i][j]=1;
}
}
For(i,1,2001)
For(j,1,2001){
if (!vis[i+1][j]&&!vis[i-1][j]&&!vis[i][j+1]&&!vis[i][j-1]){
if (!vis[i+1][j-1]&&!vis[i-1][j+1]&&vis[i+1][j+1]&&vis[i-1][j-1]) vis[i][j]=1;
if (vis[i+1][j-1]&&vis[i-1][j+1]&&!vis[i+1][j+1]&&!vis[i-1][j-1]) vis[i][j]=1;
}
else{
if (!vis[i][j]&&vis[i-1][j]&&vis[i+1][j]) vis[i][j]=1;
if (!vis[i][j]&&vis[i][j-1]&&vis[i][j+1]) vis[i][j]=1;
else if (vis[i][j]&&!vis[i-1][j]&&!vis[i+1][j]) vis[i][j]=0;
else if (vis[i][j]&&!vis[i][j-1]&&!vis[i][j+1]) vis[i][j]=0;
}
}
}
il vd bfs(int start_l,int start_r){
h=0,t=1;
int i,j;
l[1]=start_l,r[1]=start_r;
b[l[1]][r[1]]=1;
while (h<t){
h++;
For(k,0,3){
i=l[h]+dx[k],j=r[h]+dy[k];
if (i<0||j<0||i>2001||j>2001) continue;
if (vis[i][j]||b[i][j]) continue;
l[++t]=i,r[t]=j,b[i][j]=1;
}
}
}
int main(){
n=read();
if (n<4){
printf("0");
return 0;
}
For(i,1,n){
x1=read()+1001,y1=read()+1001,x2=read()+1001,y2=read()+1001;
if (x1==x2){
For(j,min(y1,y2),max(y1,y2)) mp[x1][j]=1;
}
else {
For(j,min(x1,x2),max(x1,x2)) mp[j][y1]=1;
}
}
bfs();
For(i,0,2001)
For(j,0,2001)
if (!vis[i][j]&&!b[i][j]) {
bfs(i,j);
if (l[t]!=i&&r[t]!=j) ans++;
}
printf("%d",ans);
}