Barn Expansion
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2305 | Accepted: 607 |
Description
Farmer John has N (1 <= N <= 25,000) rectangular barns on his farm, all with sides parallel to the X and Y axes and integer corner coordinates in the range 0..1,000,000. These barns do not overlap although they may share corners and/or sides with other barns.
Since he has extra cows to milk this year, FJ would like to expand some of his barns. A barn has room to expand if it does not share a corner or a wall with any other barn. That is, FJ can expand a barn if all four of its walls can be pushed outward by at least some amount without bumping into another barn. If two barns meet at a corner, neither barn can expand.
Please determine how many barns have room to expand.
Since he has extra cows to milk this year, FJ would like to expand some of his barns. A barn has room to expand if it does not share a corner or a wall with any other barn. That is, FJ can expand a barn if all four of its walls can be pushed outward by at least some amount without bumping into another barn. If two barns meet at a corner, neither barn can expand.
Please determine how many barns have room to expand.
Input
Line 1: A single integer, N
Lines 2..N+1: Four space-separated integers A, B, C, and D, describing one barn. The lower-left corner of the barn is at (A,B) and the upper right corner is at (C,D).
Lines 2..N+1: Four space-separated integers A, B, C, and D, describing one barn. The lower-left corner of the barn is at (A,B) and the upper right corner is at (C,D).
Output
Line 1: A single integer that is the number of barns that can be expanded.
Sample Input
5 0 2 2 7 3 5 5 8 4 2 6 4 6 1 8 6 0 0 8 1
Sample Output
2
Hint
Explanation of the sample:
There are 5 barns. The first barn has its lower-left corner at (0,2) and its upper-right corner at (2,7), and so on.
Only two barns can be expanded --- the first two listed in the input. All other barns are each in contact with at least one other barn.
大体题意:
给你n个矩形,告诉你矩形的左下角坐标和右上角坐标,求出有多少矩形是完全独立的,就是说不与其他矩形有点或线的接触。
思路:
玩了很久了,才补完这道题目,补完睡觉了= =!
题目中给的矩形都是平行于x轴和y轴的,所以可以直接判断横线和竖线是否接触!
方法是:
先考虑竖线吧(a,b)这个点,定义一个线类,有值key,因为是竖线,x坐标都一样,所以值就是横坐标,
key = a, y坐标从b到d,所以起点是b,终点是d。 (还需注意一个矩形的四条线的id都是一样的)
这样构造完所有竖线后,给他们排个序,先按值从小排序(方便枚举)相等的话按照起点排序。
然后开始枚举所有竖线,如果下一个线的起点比上一个线的终点小的话,说明有接触了,把这两条线的id 都记为已接触。
注:因为平行线段要接触必须共线了,所以先找值一样的所有线段(不这样做会超时)
以同样的方法构造枚举横线。
最后枚举横线加竖线,把没接触的线加起来即可!
这就是平面扫描
详细见代码:
There are 5 barns. The first barn has its lower-left corner at (0,2) and its upper-right corner at (2,7), and so on.
Only two barns can be expanded --- the first two listed in the input. All other barns are each in contact with at least one other barn.
大体题意:
给你n个矩形,告诉你矩形的左下角坐标和右上角坐标,求出有多少矩形是完全独立的,就是说不与其他矩形有点或线的接触。
思路:
玩了很久了,才补完这道题目,补完睡觉了= =!
题目中给的矩形都是平行于x轴和y轴的,所以可以直接判断横线和竖线是否接触!
方法是:
先考虑竖线吧(a,b)这个点,定义一个线类,有值key,因为是竖线,x坐标都一样,所以值就是横坐标,
key = a, y坐标从b到d,所以起点是b,终点是d。 (还需注意一个矩形的四条线的id都是一样的)
这样构造完所有竖线后,给他们排个序,先按值从小排序(方便枚举)相等的话按照起点排序。
然后开始枚举所有竖线,如果下一个线的起点比上一个线的终点小的话,说明有接触了,把这两条线的id 都记为已接触。
注:因为平行线段要接触必须共线了,所以先找值一样的所有线段(不这样做会超时)
以同样的方法构造枚举横线。
最后枚举横线加竖线,把没接触的线加起来即可!
这就是平面扫描
详细见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 25000 + 10;
struct Node {
int a,b,c,d;
void read(int aa,int bb,int cc,int dd){
a = aa; b = bb; c = cc; d = dd;
}
}p[maxn];
struct Line{
int key,st,ed;
int id;
bool operator < (const Line& rhs) const {
return key < rhs.key || (key == rhs.key && st < rhs.st);
}
}l[maxn<<1];
int vis[maxn<<1];
int main(){
int n;
scanf("%d",&n);
for (int i = 0 ; i < n; ++i){
int a,b,c,d;
scanf("%d %d %d %d",&a,&b,&c,&d);
p[i].read(a,b,c,d);
}
for (int i = 0; i < n; ++i){
l[2*i].key = p[i].a;
l[2*i].st = p[i].b;
l[2*i].ed = p[i].d;
l[2*i].id = i;
l[2*i+1].key = p[i].c;
l[2*i+1].st = p[i].b;
l[2*i+1].ed = p[i].d;
l[2*i+1].id = i;
}
sort(l,l+2*n);
int i,j;
for (i = 0; i < 2*n; ++i){
for (j = i; j < 2*n; ++j){
if (l[j].key != l[i].key)break;
}
int up = l[i].ed;
for (int k = i+1; k < j; ++k){
if (l[k].st <= up){
vis[l[k].id] = vis[l[k-1].id ] = 1;
}
up = max(up,l[k].ed);
}
i=j-1; // 注意,i不变的话 会超时!!
}
for (int i = 0; i < n; ++i){
l[2*i].key = p[i].b;
l[2*i].st = p[i].a;
l[2*i].ed = p[i].c;
l[2*i].id = i;
l[2*i+1].key = p[i].d;
l[2*i+1].st = p[i].a;
l[2*i+1].ed = p[i].c;
l[2*i+1].id = i;
}
sort(l,l+2*n);
for (i = 0; i < 2*n; ++i){
for (j = i; j < 2*n; ++j){
if (l[j].key != l[i].key)break;
}
int up = l[i].ed;
for (int k = i+1; k < j; ++k){
if (l[k].st <= up){
vis[l[k].id] = vis[l[k-1].id ] = 1;
}
up = max(up,l[k].ed);
}
i=j-1; // 注意,i不变的话 会超时!!
}
int ans = 0;
for (int i = 0; i < n; ++i){
if (!vis[i])++ans;
}
// ans/=4;
printf("%d\n",ans);
return 0;
}