1. 程式人生 > >1328 區間貪心

1328 區間貪心

主要的思路就是將這個題目轉換一下去求。題目上面說,雷達只會在x軸上面,那麼我們就可以去算一下大致的幾種情況:

第一種,雷達全面覆蓋的到。那麼轉換一下思路。

第二種,存在幾個特殊的,比較高的位置,雷達無法覆蓋,就是雷達最高為m,但是他的位置高度超過了m,所以直接輸出-1.

思路就是我們可以把每一個點轉換一下,看成一個圓,去思考一下。如果點可以被覆蓋的到,那麼圓與x軸就會相交或者相切,以半徑為雷達m範圍的圓。如果他們不相交,那麼就是說雷達掃描不到,因為雷達只在x軸上面。

如圖:

在這裡我們看見了因為相交的部分不重合,所以要想在x軸上面安雷達覆蓋這兩個點,我們至少需要兩個。

如圖的思想,我們再加一個點所構成的圓。在此註明一點就是,在x軸上面的範圍就是表明雷達如果要覆蓋這點,那麼他就必須在這個範圍裡面。因為二點,一必須在x軸上面,二他是以雷達範圍的圓,不在就說明點與雷達的範圍超過了雷達掃描的範圍。

在此圖,我們可以更好的看出如果,範圍重合了,就說明他們可以用一個雷達去掃描得到。

最後得到的其實就是這個圖了,求的就是公共覆蓋的就用一點,不是公共覆蓋的就開闢,把一個範圍不斷的縮小,縮小的區域就是共同的雷達,不在縮小的區域類,就代表著,存在一點和你不含有公共區域。

所以題目的思路就清晰了,先把點轉化為在x軸上面的範圍,求範圍的話,根據數學的公式就可以求出來了。[x-根號下(r*r-y*y),x+根號下(r*r-y*y)],這個範圍就可以了。最後題目就轉換成了求公共覆蓋範圍用一個雷達,不在就新建一個雷達。

 

既然我要用一個圓嘗試著(雷達範圍,半徑為r)去覆蓋島嶼,那為何不以島嶼為圓心r為半徑畫一個圓(記為圓O),於是只要雷達在這個圓裡那麼這個島嶼就能被覆蓋。而從前面的分析可知,雷達必然要佈置在x軸上,所以雷達肯定放在圓O與x軸的那段交線區間上,如圖:

所以我們可以將所有的島嶼對應的這段區間記錄下來,然後以區間左界從小到大排序就行,之後從第一個區間開始,如果第二個區間與其有交集,就更新這個交集,並從佇列中除去區間1,2,如果第三個區間與這個交集又有交集,那麼便更新交集併除去區間3直到不滿足有交集為止。然後繼續模擬這個過程就行了,每模擬以此這個過程ANS++(即區間選點問題)
 

但是這道題注意浮點誤差!以及sqrt(double)的使用

#include<cmath>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define MAXN 1010
using namespace std;
struct node 
{
	double xl;//最左可被偵測座標
	double xr;//最右可被偵測座標
}island[MAXN];
int n,d,x,y,cnt,flag;
double offset;
 
bool cmp(node a,node b)
{
	return a.xl<b.xl;
}
 
int find()
{
	int num=0;
	double cur; 	//當前最右可被偵測座標 
	cur=island[1].xr;
	num++;
	for(int i=2;i<=n;i++)
	{
		if(island[i].xl-cur>1e-6) //下個島嶼的最左座標大於當前最右可被偵測座標 
		{
			num++;
			cur=island[i].xr;
		}
		else
			if(island[i].xr-cur<1e-6) //下個島嶼的最右座標小於當前最右可被偵測座標 
			    cur=island[i].xr;
	}
	return num; 
}
 
int main()
{
    while(~scanf("%d %d",&n,&d))
    {
    	if(n==0&&d==0)break;
        flag=0;
        cnt++;
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d",&x,&y);
            if(y>d)	flag=1;
            
            offset=sqrt((double)(d*d-y*y));
            
            island[i].xl=x-offset;
            island[i].xr=x+offset;
        }
        if(flag)
        {
            printf("Case %d: -1\n",cnt);
            continue;
        }
        sort(island+1,island+n+1,cmp);
        int ans=find();
        printf("Case %d: %d\n",cnt,ans);
    }
    return 0;
}