坐标离散化
传入数组对(x1,x2)和范围w,可以将他们离散成小范围。
int compress(int *x1,int *x2,int w){
vector<int> xs;
for(int i=0;i<N;i++){
for(int d=-1;d<=1;d++){
int tx1=x1[i]+d,tx2=x2[i]+d;
if(1<=tx1&&tx1<=w) xs.push_back(tx1);
if(1<=tx2&&tx2<=w) xs.push_back(tx2);
}
}
sort(xs.begin(),xs.end());
xs.erase(unique(xs.begin(),xs.end()),xs.end());
for(int i=0;i<N;i++){
x1[i]=find(xs.begin(),xs.end(),x1[i])-xs.begin();
x2[i]=find(xs.begin(),xs.end(),x2[i])-xs.begin();
}
return xs.size();
}
例如:
WxH的格子上有n条垂直或水平宽度为1的直线。求这些直线将格子划分了多少个区域。
完整代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
#include<queue>
using namespace std;
const int Maxn=1024;
int W,H,N,x1[Maxn],x2[Maxn],y1[Maxn],y2[Maxn],dir[4][2]={-1,0,0,1,1,0,0,-1};
bool fld[Maxn][Maxn];
int compress(int *x1,int *x2,int w){
vector<int> xs;
for(int i=0;i<N;i++){
for(int d=-1;d<=1;d++){
int tx1=x1[i]+d,tx2=x2[i]+d;
if(1<=tx1&&tx1<=w) xs.push_back(tx1);
if(1<=tx2&&tx2<=w) xs.push_back(tx2);
}
}
sort(xs.begin(),xs.end());
xs.erase(unique(xs.begin(),xs.end()),xs.end());
for(int i=0;i<N;i++){
x1[i]=find(xs.begin(),xs.end(),x1[i])-xs.begin();
x2[i]=find(xs.begin(),xs.end(),x2[i])-xs.begin();
}
return xs.size();
}
void solve(){
W=compress(x1,x2,W);
H=compress(y1,y2,H);
memset(fld,false,sizeof(fld));
for(int i=0;i<N;i++){
for(int y=y1[i];y<=y2[i];y++){
for(int x=x1[i];x<=x2[i];x++){
fld[y][x]=true;
}
}
}
int ans=0;
for(int i=0;i<H;i++){
for(int j=0;j<W;j++){
if(fld[i][j]) continue;
ans++;
queue<pair<int,int> >que;
que.push(make_pair(i,j));
while(!que.empty()){
int nx=que.front().first,ny=que.front().second;que.pop();
for(int k=0;k<4;k++){
int tx=nx+dir[k][0],ty=ny+dir[k][1];
if(tx<0||ty<0||tx>=H||ty>=W||fld[tx][ty]) continue;
que.push(make_pair(tx,ty));
fld[tx][ty]=true;
}
}
}
}
printf("%d\n",ans);
}
int main(){
while(~scanf("%d%d%d",&W,&H,&N)){
for(int i=0;i<N;i++){
scanf("%d %d %d %d",&x1[i],&x2[i],&y1[i],&y2[i]);
}
solve();
}
}