POJ 1328

题意:

一个直角座标系,x轴上方有N个点。

现要求画若干个圆心在x轴上,半径为R的圆,将N个点包含(内部或边界)

输入最小的圆的数量。

不存在则输出-1

 

思路:

对于每个点分析,如纵座标大于R则不存在可行方案

否则在x轴上存在一区间上所有点皆符合条件(点间距小于或等于R)

 

子问题:线性区间选点

给定n个区间,要求选若干个点,保证每个区间内都有点被选,输出点的最小数目

 

子问题思路:

将区间按照右边界升序排序,相同右边界也按升序排序。

每次选取当前区间最右点。然后跳过左边界小于此点的区间继续计数即可。

 

贪心思路证明:

 

对于当前区间选取中间某一点,同时影响了m个区间

将此点移动到本区间末,影响区间数目不会减小,甚至有可能影响更多的区间。


#include <stdio.h>
#include <algorithm>
#define LL long long

using namespace std;

struct aa
{
	int l;
	int r;
};
aa area[101000];

bool cmp(const aa &a, const aa &b)
{
	if(a.r!=b.r)
		return a.r < b.r;
	return a.l < b.l;
}

int main()
{
	int n, r;
	int case_num = 1;
	while(scanf("%d %d", &n, &r)==2 && (n||r))
	{
		int flag = 0;

		for (int i = 0; i < n; i++)
		{
		    int x, y;
			scanf("%d %d", &x, &y);
			if(y > r)
            {
				flag = 1;
				continue;
            }

			int diff = 0;
			for(; ;diff++)
				if(((LL)diff*diff + (LL)y*y) > (LL)r*r)
					break;
			diff--;
			area[i].l = x-diff;
			area[i].r = x+diff;
		}

		if(flag)
		{
			printf("Case %d: -1\n", case_num++);
			continue;
		}

		sort(area, area + n, cmp);

		int res = 1;
		int right = area[0].r;
		for (int i = 1; i < n; ++i)
		{
			if(area[i].l>right)
			{
				res++;
				right = area[i].r;
			}
		}
		printf("Case %d: %d\n", case_num++, res);
	}
}

WA
发布了30 篇原创文章 · 获赞 0 · 访问量 9158
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章