蓝桥杯真题 平面切分(Set自定义去重)
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
平面上有 N 条直线,其中第 i 条直线是 y=Ai⋅x+Bi。
请计算这些直线将平面分成了几个部分。
输入格式
第一行包含一个整数 N。
以下N行,每行包含两个整数 Ai,Bi。
输出格式
一个整数代表答案。
样例输入
3
1 1
2 2
3 3
Data
样例输出
6
评测用例规模与约定
对于 50 的评测用例,1≤N≤4, −10≤Ai,Bi≤10。
对于所有评测用例,1≤N≤1000, −100000≤Ai,Bi≤100000。
考点
去重,思路
思路:
对于第一条线,它会将平面分成两个部分,对于之后每加入一条线:
-
如果与其它线互不相交:1、平行,那么会多划分出一个平面(+1)。2、重合,不会发生改变
-
如果与其它线相交:那么每产生一个交点,就会额外多划分一个平面(+2)。这里有一点要注意:当产生的交点中有重复的点,只需要算一次即可
可以发现在判断线和点时都需要进行去重,对于所有不重合的线,保底会使的平面划分+1,当产生新的交点时,会额外使平面划分+1
以下三种情况是可能的图像:

代码
1 import java.util.ArrayList; 2 import java.util.HashSet; 3 import java.util.List; 4 import java.util.Scanner; 5 import java.util.Set; 6 7 public class Main { 8 static class Pair { 9 double a; 10 double b; 11 12 public Pair(double a, double b) { 13 this.a = a; 14 this.b = b; 15 16 } 17 18 // 重写hashCode方法 19 // hasCode不能直接判断两个值相等,但能直接判断两个值不相等 20 // 相当于做了一个预处理 21 @Override 22 public int hashCode() { 23 return (int) a; 24 } 25 26 // 重写equals方法 27 @Override 28 public boolean equals(Object obj) { 29 // TODO Auto-generated method stub 30 Pair p = (Pair) obj; 31 return this.a == p.a && this.b == p.b; 32 } 33 } 34 35 public static void main(String args[]) { 36 Scanner in = new Scanner(System.in); 37 Set<Pair> set = new HashSet<>(); 38 Set<Pair> point = new HashSet<>(); 39 int n = in.nextInt(); 40 for (int i = 0; i < n; i++) { 41 double a = in.nextDouble(); 42 double b = in.nextDouble(); 43 set.add(new Pair(a, b)); 44 } 45 int len = set.size(); 46 List<Pair> arr = new ArrayList<>(); 47 arr.addAll(set); 48 int ans = 2;// 第一条直线把平面分成两块 49 for (int i = 1; i < len; i++) { 50 point.clear();// 记得清零 51 for (int j = 0; j < i; j++) { 52 double a1 = arr.get(i).a; 53 double a2 = arr.get(j).a; 54 double b1 = arr.get(i).b; 55 double b2 = arr.get(j).b; 56 if (a1 == a2) 57 continue; // 平行没有交点 58 double x = (b2 - b1) / (a1 - a2); 59 double y = a1 * x + b1; 60 point.add(new Pair(x, y));// 将交点去重 61 } 62 ans += (point.size() + 1);// +1是默认的 63 } 64 System.out.println(ans); 65 } 66 }
关于Set自定义类型的去重
而判断的依据就是通过元素类中的hasCode函数和equals函数。
所以当我们想要用Set对自定义类去重时,要重写这两个函数。
equals()
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
Pair p = (Pair) obj;
return this.a == p.a && this.b == p.b;
}
顾名思义,用来判断两个元素在满足什么样的条件被认为是“相同”的,这个条件可以自己来定。
hasCode()
@Override
public int hashCode() {
return (int) a;
}
返回值为int型的函数,主要用来在散列存储结构中确定对象的位置。
当我们用Set去重的时候,如果对每个元素都要进行一次相等比较,开销非常大,所以在集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,如果之前没有出现过改hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较。
我觉得hasCode是对于数据做了一个预处理,帮助减少equals的使用次数,如果两个对象的hasCode值都不同,那么元素本身肯定也不相同
记住,equals判断相等,hasCode判断不相等

浙公网安备 33010602011771号