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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章