您的位置:首页 > 运维架构

USACO2011Open Bronze 3lines 题解

2016-06-28 17:01 393 查看
[思路]

符合 FJ的要求有两种情况:三条直线平行或者两条直线平行并与一条直线垂直.至于横竖的问题,可以通过反转奶牛的坐标转化成相同的方式.

三条平行直线:

把所有点的横坐标记录下来,如果不同的横坐标个数小于等于3,那么符合条件.

两条平行与一条直线垂直:
把所有的纵坐标和它们个数记下,也记下所有出现的纵坐标个数,再按照横坐标排序,再枚举一个横坐标a,表示这条直线x=a与其他两条横线垂直,再把这条直线上的所有纵坐标cnt--,再看纵坐标出现的个数,如果<=2,说明成立.

标程写的比我的精炼很多,那我就放标程吧…

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
const int MAXN = 1001000;
pair<int,int> lis[MAXN];
map<int, int> cou;
int distinct;
int n;
void inc(int x) {
if(cou[x] == 0) {
distinct++;//不同纵坐标的个数
}
cou[x] = cou[x] + 1;
}

void dec(int x) {
cou[x] = cou[x] - 1;
if(cou[x] == 0) distinct--;
}

int moo() {
sort(lis, lis + n);//排序,把相同横坐标的放在一起
distinct = 0;
cou.clear();
for(int i = 0; i < n; ++i) {
inc(lis[i].second);
}
if(distinct <= 3) return 1;//三条平行
int i = 0, i1 = 0;
while(i < n) {
while(i1 < n && lis[i].first == lis[i1].first) i1++;
for(int i2 = i; i2 < i1; ++i2) dec(lis[i2].second);//删除一条竖线上的所有纵坐标
if(distinct <= 2)  return 1;
for(int i2 = i; i2 < i1; ++i2) inc(lis[i2].second);
i = i1;
}
return 0;
}
int main() {
scanf("%d", &n);
for(int i = 0; i < n; ++i)
scanf("%d%d", &lis[i].first, &lis[i].second);
if(moo()) {
puts("1");
}
else {
for(int i = 0; i < n; ++i) {
swap(lis[i].first, lis[i].second);//把坐标反转
}
if(moo()) puts("1");
else puts("0");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  USACO