原理:从稀疏矩阵中把有效数据提出来,放在一个新的坐标系中
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cstring>
const int INF = 1e6;
const int maxn = 510;
using namespace std;
int W, H, N;
int X1[maxn], X2[maxn], Y1[maxn], Y2[maxn];
int mp[maxn][maxn];
//填充用
bool fld[maxn * 6][maxn * 6];
//对x1 x2进行坐标离散化,返回离散化之后的值
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;
int 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, 0, sizeof(fld));
for(int i = 0; i < N; i++)
for(int j = Y1[i]; j <= Y2[i]; j++)
for(int k = X1[i]; k <= X2[i]; k++)
fld[j][k] = 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 sx = que.front().first;
int sy = que.front().second;
que.pop();
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};
for(int i = 0; i < 4; i++){
int tx = sx + dx[i];
int ty = sy + dy[i];
if(H <= tx || tx < 0 || W <= ty || ty < 0)continue;
if(fld[tx][ty])continue;
fld[tx][ty] = true;
que.push(make_pair(tx, ty));
}
}
}
}
printf("%d\n", ans);
}
//测试函数
int main(){
freopen ("D:\\钢铁程序员\\程序数据\\072坐标离散化.txt","r",stdin);
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();
return 0;
}