题目按难度从简到难手动排序————题记
T1:三笔画(3lines)
【题目描述】:
二维平面内有 n 个不同的点, Alice 需要在平面内画至多 3 条直线使得所有点在直线上。
问: Alice 能否完成任务, 如果能, 输出”YES”; 否则, 输出”NO”。
注意: 由于 Alice 的画图水平有限, 直线只能平行于坐标轴。
【输入数据】:
第一行,一个整数 n。
接下来 n 行,第 i+1 行包含空格隔开的整数 xi,yi,表示第 i 个点的坐标。
【输出数据】:
若 Alice 能完成任务, 输出”YES”, 否则输出”NO”。
【样例输入】:
6
1 7
0 0
1 2
2 0
1 4
3 4
【样例输出】:
YES
【样例解释】:
三条直线分别为 x=1,y=0,y=4。
【数据范围】:
对于 30%的数据,1 <= n <= 13。
对于 60%的数据,1 <= n <= 20。
对于 100%的数据,1 <= n <= 5e4,0 <= xi, yi <= 1e9。
心路历程:对于这道题,在考场上我思考了很久,经过分析,我发现如果在一条线上有超过3个点,说明必须要使用一条线去覆盖这几个点,就使 L i n e − 1 Line-1 Line−1( L i n e Line Line初始值为3),将这几个点删去。如果没有这种情况,那么就暴力枚举剩余Line条线,判断是否可以覆盖。对于大数据,这种方法很有效,对于小数据,那就直接暴力吧!【φ(>ω<*)】
正解:对于三条直线的状态,只有以下2种状态:
- 1. 1. 1.三条水平线
- 2. 2. 2.两条水平线+一条垂直线
(剩余情况旋转坐标轴即可)
我们用一个数组统计同一 y y y 坐标上有几个点。
对于 ① 的情况,只需判断是否只有三个及以下的 y y y 坐标上有点即可。
对于 ② 的情况,可以枚举垂直线的 x 坐标,将这条垂直线上的点全部删去,判断剩下的点的 y y y 坐标是否只有两种及以下。
因为 x i , y i xi,yi xi,yi有些大,可以先进行离散化预处理后再进行操作。
将点按 x x x 坐标排序后即可做到 O ( n ) O(n) O(n)的扫描.
非正解代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 600000;
int n;
int x[N], y[N];
bool check(int p1,int t1,int p2,int t2,int p3,int t3)
{
int ans = 0;
for (int i=1;i<=n;++i) {
if (x[i] == p1 && t1 == 1) ans ++;
else if (x[i] == p2 && t2 == 1) ans ++;
else if (x[i] == p3 && t3 == 1) ans ++;
else if (y[i] == p1 && t1 == 2) ans ++;
else if (y[i] == p2 && t2 == 2) ans ++;
else if (y[i] == p3 && t3 == 2) ans ++;
}
return ans == n;
}
bool work1(void)
{
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
for (int k=1;k<=n;++k) {
if (check(x[i],1,x[j],1,x[k],1)) return 1;
if (check(x[i],1,x[j],1,y[k],2)) return 1;
if (check(x[i],1,y[j],2,x[k],1)) return 1;
if (check(x[i],1,y[j],2,y[k],2)) return 1;
if (check(y[i],2,x[j],1,x[k],1)) return 1;
if (check(y[i],2,x[j],1,y[k],2)) return 1;
if (check(y[i],2,y[j],2,x[k],1)) return 1;
if (check(y[i],2,y[j],2,y[k],2)) return 1;
}
return 0;
}
bool work2(void)
{
map <int,int> cnt1;
map <int,int> cnt2;
map <int,int> cnt3;
map <int,int> cnt4;
int cnt_x = 0, cnt_y = 0, P = -1, T = -1;
for (int i=1;i<=n;++i)
cnt1[x[i]] ++, cnt2[y[i]] ++;
for (int i=1;i<=n;++i)
{
if (cnt1[x[i]] > 3) {
P = x[i], T = 1;
break;
}
if (cnt2[y[i]] > 3) {
P = y[i], T = 2