AcWing 4309. 消灭老鼠 java 向量 欧几里得

文章讲述了在处理编程竞赛中的坐标轴问题时,如何处理分母为0(y轴)和分子为0(x轴)的情况,以及如何通过最小公约数和映射策略来解决斜率相同点的去重问题。示例代码中使用了HashMap和TreeSet进行数据结构的去重操作。
摘要由CSDN通过智能技术生成

🤠 原题地址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

⭐ 无脑求 k 版(不得不说,卡精度真🤮)

① 当分母为 0 时,即处于 y 轴上时,k == infinite,而且还有 + -,特判
② 当分子为 0 时,即处于 x 轴上时,k  ==  0,也分 + - ,特判
③ 去重乱写,高兴就行
import java.util.*;

public class 消灭老鼠
{
	static int N = 1010;
	static double x, y;

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		x = sc.nextDouble();
		y = sc.nextDouble();
		HashMap<Double, Integer> map = new HashMap<>();
		for (int i = 0; i < n; i++)
		{
			double xx = sc.nextDouble();
			double yy = sc.nextDouble();
			double k = 0.0;
			if (y - yy == 0)
				k = 0.0;
			else if (x - xx == 0)
				k = Math.abs(y - yy) / x - xx;
			else
			{
				k = (y - yy) / (x - xx);
			}
			System.out.println(i + 1 + " " + xx + " " + yy);
//			if (i == 40)
//			{
//				System.out.println();
//			}
			System.out.println(i + 1 + " " + k);

//			if(x-xx==0)

			if (!map.containsKey(k))
			{
				map.put(k, 1);
			}
		}

		System.out.println(map.size());
	}
}

⭐ 最小公约数(向量)(避开精度问题) 优化版

① 将 x y 置为坐标原点,(0,0)所有横竖坐标减去 x y 即可实现
② 斜率相同即可一次消灭,但求斜率涉及除法运算,细节较多,将斜率映射成最小公约数的坐标对即可实现简单判重
  例:假设 x = 0, y = 0; (映射:横竖坐标同时除以其最大公约数)下边 []:表示最大公约数
  点(6,3)[3] -> (2,1)  k = 2
  点(8,4)[4] -> (2,1) k = 2
  点 (-2,-4)-》 (2,4) [2] -> (2,1) k = 2
  k相同的的点,映射的点也相同
  x负半轴区域也是如此
  点 (-1,3)-》(1,-3)[1] -> (1,-3)
  点 (2,-6)[2] -> (1,-3) 
③ 左边区域的点全部映射到右边区域,便于求最小公约数映射
④ (java)treeset 重写比较器实现对自定义类的去重操作
import java.util.*;

public class Main
{
	static int n, x, y;

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		x = sc.nextInt();
		y = sc.nextInt();

//      TreeSet 可以重写 cmpareto 方法实现 对自定义类的去重 return 0 表示重复元素
//      这里是实现 x y 不重复的 lambda 表达式实现,也可以 自定义类 继承 comparable接口 实现 compareto 方法
		TreeSet<Pair> set = new TreeSet<>((o1, o2) -> {
			if (o1.y == o2.y)
				return o1.x - o2.x;
			else
				return o1.y - o2.y;
		});
//		HashSet<Pair> set = new HashSet<>();// set去重自定义对象需要重写 equals方法
//		HashMap<Integer, Integer> map = new HashMap<>(); // hashmap 只能对键进行去重

		for (int i = 0; i < n; i++)
		{
			int a = sc.nextInt();
			int b = sc.nextInt();
//			把原点设在 (x,y)处
			a -= x;
			b -= y;
			int c = gcd(a, b);
			a /= c;
			b /= c;

			if (a < 0)// 坐标轴左边的全部映射到右边
			{
				a = -a;
				b = -b;
			}
			set.add(new Pair(a, b));
//			if (!map.containsKey(a))
//			{
//				map.put(a, b);
//			}
		}
		System.out.println(set.size());
//		System.out.println(map.size());

	}

	private static int gcd(int a, int b)
	{
		return b == 0 ? a : gcd(b, a % b);
	}

	static class Pair
	{
		int x;
		int y;

		public Pair(int x, int y)
		{
			super();
			this.x = x;
			this.y = y;
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值