HDU1922 POJ3004 Subway planning “神題”留名

Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=1922


【前言】


xlj問我有沒有題做,沒有的話給我一道。

我說我正在做,等一下。

然後敲完了一道離散的題,然後接過了這道題。

想了段時間之後找到了做法。

發現xlj的想法也是一樣。

於是開始敲。誰知道這纔是悲劇的開始。

敲好後debug過了sample,交之後狂WA。

hdu1922這道題只有幾個人過了這道題,解題報告也找不到。

然後各種能考慮的情況都考慮進去,還是WA。

最後找到了解題報告,發現原來是poj3004。

做法也是一樣的思路。

但還是WA。

前前後後在HDU上交了二十多次,在poj上交了幾次。

xlj回來後繼續,但是sample還沒過。

後來發現他裏面錯漏百出。然後就改啊改。

但我的還是WA。

找到一份代碼對照之後還是WA。

回宿舍後又提交了十幾二十次,還是WA。

終於,在臨近十二點的時候,發現了錯誤。

第一處錯誤是少寫了一個字母,後來發現的時候,

雖然改過來了,但是下面又改錯了。

於是華麗麗地傻×了。

如果沒有那處錯誤的話,應該早就過了。

所以,這道題雖然出的很好,是神題,但並不是真的神了,而是我傻了……


【思路】


首先,如果某個點可以覆蓋到原點,則把那個點直接去掉。

對於每個點,找出它的極角範圍。從原點引該點半徑爲d的圓的兩條切線,然後計算出切線的兩個極角。

每個點都有兩個極角,變成了貪心的區間覆蓋問題。

要求自定義的區間個數,使所有的已知區間都包含這些區間,要使區間個數最小。

由於是圓環,所以掃描每個點,以該點作爲斷點,然後貪心一遍,取它們的最小值。


【代碼】


#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

#define min(a,b) ((a)<=(b)?(a):(b))

const int maxn = 1000;
const double pi = acos(-1.0);

struct point
{
    double x, y;
    double l, r;
}pt[maxn*2+1];

bool cmp(const point &a, const point &b)
{
    return a.l<b.l;
}

void set(point &p, double d, double dis)
{
    double a, b;
    if (p.x==0)
    {
        if (p.y>0) a = 0.5*pi;
        else a = 1.5*pi;
    }
    else if (p.y==0)
    {
        if (p.x>0) a = 0;
        else a = pi;
    }
    else
    {
        a = asin(fabs(p.y*1.0)/dis);
        if (p.x<0 && p.y>=0) a = pi - a;
        else if (p.x<=0 && p.y<0) a += pi;
        else if (p.x>0 && p.y<=0) a = 2*pi-a;
    }
    b = asin(1.0*d/dis);
    p.l = a-b;
    p.r = a+b;
}

double dist(double x, double y)
{
	return sqrt(x*x+y*y);
}

int main()
{
    int t;
    int n;
    double d;
    int i, j;
    int ct;
	double d1;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d %lf", &n, &d);
        for (i=0; i<n; i++)
        {
            scanf("%lf %lf", &pt[i].x, &pt[i].y);
			d1 = dist(pt[i].x, pt[i].y);
			if (d1<=d)
			{
				i--;
				n--;
			}
			else set(pt[i], d, d1);
        }
        sort(pt, pt+n, cmp);
		for (i=n; i<2*n; i++)
		{
			pt[i].l = pt[i-n].l+2*pi;
			pt[i].r = pt[i-n].r+2*pi;
		}
		int ans = 1000000;
		for (j=0; j<n; j++)
		{
			ct = 1;
			double s = pt[j].r;
			for (i=1+j; i<n+j; i++)
			{
				if (s<pt[i].l)
				{
					ct++;
					s = pt[i].r;
				}
				else
				{
					s = min(s, pt[i].r);
				}
			}
			ans = min(ans, ct);
		}
		if (ans==1000000) ans = 0;
		printf("%d\n", ans);
    }
    return 0;
}


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