蓝桥杯真题 平面切分(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自定义类型的去重

首先我们要知道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判断不相等

posted @ 2022-04-08 19:40  JaineCC  阅读(202)  评论(0)    收藏  举报