题目描述
FJ想使用购买的新监控系统监视他的N头奶牛(1 <=N<= 50,000)。
第i头牛位置在(x_i, y_i),这是一对整数坐标,范围在0…1,000,000,000之内。FJ的监控系统有3个特殊的镜头,每一个镜头能够观察垂直或者水平的一行。
请决定FJ是否有可能架设这3个镜头,使他能够观察到所有的N头牛。也就是说,请决定N头牛的位置是否能同时被3条直线所覆盖。这3条直线必须是垂直或者水平的。
输入
第1行:1个整数N
第2..N+1行:2个整数x_i和y_i,表示第i头牛的坐标
输出
第1行:如果能监控所有的N头牛,则输出1,否则输出0
样例输入
6
1 7
0 0
1 2
2 0
1 4
3 4
样例输出
1
思路
这题DFS爆搜。
首先,用c[i]来记录i这行或这列的奶牛数,用d来记录还有多少行或列没有被覆盖。
如果一次循环过去d<=3就直接退出;
否则,去枚举覆盖这个点,能不能将所有点覆盖,也就是d<=2。能就退出,不能就回溯。
如果一次dfs枚举不出来,我们就将横竖坐标交换,再做一次dfs
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
const int maxn=1001000;
pair<int,int> l[maxn];
map<int, int> c;
int d;
int n;
void inc(int x)
{
if(c[x]==0) d++;
c[x]=c[x] + 1;
}
void dec(int x)
{
c[x]=c[x]-1;
if(c[x]==0) d--;
}
int dfs() {
sort(l,l+n);
d= 0;
c.clear();
for(int i=0;i<n;++i)
{
inc(l[i].second);
}
if(d<=3) return 1;
int i=0,j=0;
while(i<n)
{
while(j<n && l[i].first==l[j].first) j++;
for(int i2 =i; i2<j;++i2) dec(l[i2].second);
if(d<=2) return 1;
for(int i2 =i; i2<j;++i2) inc(l[i2].second);
i=j;
}
return 0;
}
int main()
{
freopen("3lines.in","r",stdin);
freopen("3lines.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d%d",&l[i].first,&l[i].second);
if(dfs())
{
printf("1");
}
else
{
for(int i=0;i<n;++i)
{
swap(l[i].first,l[i].second);
}
if(dfs()) printf("1");
else printf("0");
}
return 0;
}