NYOJ-710(贪心)-题目----------------------------------外星人的供给站

本文介绍了一种算法,用于确定覆盖一组给定圆的最小数量。通过计算每个圆的极坐标范围,并对其进行排序和合并重叠部分来解决这个问题。最终目的是找到所需的最少圆数以覆盖所有给定的亮点。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class ProblemJ {

	private static int N, count;
	private static double R, x, y, z;

	// 当前亮点的极光点圆心的范围类
	public static class Rounds {
		double leftpoint, rightpoint;

		public Rounds(double leftpoint, double rightpoint) {
			this.leftpoint = leftpoint;
			this.rightpoint = rightpoint;
		}
	}

	public static void main(String[] args) throws IOException {

		StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

		st.nextToken();
		int t = (int) st.nval;
		while (t-- > 0) {
			st.nextToken();
			N = (int) st.nval;
			st.nextToken();
			R = st.nval;
			Rounds rounds[] = new Rounds[N + 1];
			for (int i = 0; i < N; i++) {
				st.nextToken();
				x = st.nval;
				st.nextToken();
				y = st.nval;
				z = Math.sqrt(R * R - y * y);// 圆心
				// x-z是圆的圆心范围的左区间,x+z是右区间
				rounds[i] = new Rounds(x - z, x + z);
			}

			// 排序,对所有的圆...根据左区间进行排序,从小到大
			Rounds temp;
			for (int i = 0; i < N; i++)
				for (int j = i + 1; j < N; j++)
					if (rounds[i].leftpoint > rounds[j].leftpoint) {
						temp = rounds[i];
						rounds[i] = rounds[j];
						rounds[j] = temp;
					}

			count = 1;
			// 排序之后,重叠的圆(范围重叠)可以看作是一个,找出几个不连续的范围段就是需要的最少个圆
			double rightvalue = rounds[0].rightpoint;
			for (int i = 1; i < N; i++) {
				// 后一个范围段的左区间比前一个范围段的右区间大,说明是相离的两个圆,即,需要添加一个圆
				if (rounds[i].leftpoint > rightvalue) {
					count++;
					rightvalue = rounds[i].rightpoint;
				} else {
					/*
					 * 否则,则说明两种情况
					 * 1、前一个范围段和后一个范围段是有重叠一部分,此时,后一个范围段的右区间最大
					 * 2、前一个范围段完全包含后一个范围段,此时前一个范围段的右区间最大
					 * 所以这里的比较是获取到重叠的范围段最大的右区间
					 * */
					if (rounds[i].rightpoint < rightvalue) {
						rightvalue = rounds[i].rightpoint;
					}
				}
			}
			System.out.println(count);
		}
	}
}

哪有不对,希望指出来,谢谢!本人渣渣求教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值