hdu 5928 极角排序+dp

来源:互联网 发布:发淘宝链接如何粘贴 编辑:程序博客网 时间:2024/06/10 22:49



链接:戳这里


Birthday Gift
Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Problem Description

Both Mr. Frog and Wallice love running. Wallice missed Mr. Frog’s birthday recently,so he decided to give a belated birthday gift. He quickly found out an idea: he decided to run a closed curve to contain those meaningful buildings. Unfortunately, he only gets a little time left since he is going to attend an important press conference.

Wallice wants to know the maximal number of buildings can be contained in the closed curve. Note that his speed is 1.

Input

The first line contains only one integer T,which indicates the number of test cases.

For each test case, the first line contains an integer N (1≤N≤80), and a double t (0≤l≤5000) indicating the numbers of buildings Wallice cares about and the time he has.

In the following n lines, the i-th line contains two doubles xi,yi(−600≤xi,yi≤600) indicating the position of the buildings.

Output

For each test case,output one line “Case #x: ans’’,where x is the case number (starting from 1) following with ans indicating the maximum number of buildings Wallice can circled in in limited time.

Sample Input

2
4 4.1
0 0
0 1
1 0
1 1
4 3.5
0 0
0 1
1 0
1 1

Sample Output

Case #1: 4
Case #2: 3
Hint

For the second sample, Wallice does not have enough time to circle all the four buildings so he circles three of them instead.

It is guaranteed that the answer would not change even if l changes up to 10^-5, and there would not be any 3 points on one line even if any point changes its position up to 10^-5.



题意:
平面上给出n(80)个点,以及长度为L的绳子
现在要求用绳子去围点,问做多能围住多少个点


思路:

枚举当前的点st作为最下方的点,现在从st出发逆时针去绕点,最多能绕多少个点?

以st为向量的起点去极角排序

dp[i][j]表示:i点作为st能围到的逆时针上最远的点,从st-i这些点里面围j个点的最少绳子长度

然后以当前的dp[i][]去更新满足条件的dp[i+1][]

至于判断一个点是否被包围,只需要满足当前判断的点在围住的绳子左边就可以了


代码:

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>using namespace std;const double eps=-1e-8;struct point{    double x,y;    point(double x=0,double y=0):x(x),y(y){}    point operator - (const point &a)const{        return point(x-a.x,y-a.y);    }    double operator * (const point &a)const{        return x*a.y-y*a.x;    }    double operator ^ (const point &a)const{        return x*a.x+y*a.y;    }    bool operator < (const point &t)const{ /// 极角排序        bool up[2]={0,0};        if(y>0 || (y==0 && x>0)) up[0]=1;        if(t.y>0 || (t.y==0 && t.x>0)) up[1]=1;        if(up[0]^up[1]) return up[0];        return (*this)*t ? (*this)*t>0 : ((*this)^(*this))<(t^t);    }}s[110],V[110];int n;double L;double dp[110][110];double disn(point a){    return sqrt(a.x*a.x+a.y*a.y);}int main(){    int T;    scanf("%d",&T);    for(int cas=1;cas<=T;cas++){        scanf("%d%lf",&n,&L);        for(int i=1;i<=n;i++) scanf("%lf%lf",&s[i].x,&s[i].y);        int ans=0;        for(int i=1;i<=n;i++){            int m=0;            for(int j=1;j<=n;j++){                if(i==j) continue;                if(s[j].y-s[i].y>=eps) V[++m]=s[j]-s[i];            }            sort(V+1,V+m+1);            memset(dp,127,sizeof(dp));            for(int j=1;j<=m;j++){                double dis=disn(V[j]);                if(L-dis<eps) continue;                dp[j][1]=dis;                for(int k=j+1;k<=m;k++){                    double link=disn(V[k]-V[j]);                    if(L-dis-link<eps) continue;                    int cnt=1;                    for(int l=j+1;l<k;l++){                        if((V[k]-V[j])*(V[l]-V[j])>0) cnt++;                    }                    for(int l=1;l<=j && l+cnt<=k;l++){                        if(L-dp[j][l]-link<eps) continue;                        dp[k][l+cnt]=min(dp[k][l+cnt],dp[j][l]+link);                    }                }                for(int l=1;l<=m;l++) {                    if(L-dp[j][l]-dis>eps) ans=max(ans,l);                }            }        }        printf("Case #%d: %d\n",cas,ans+1);    }    return 0;}


0 0
原创粉丝点击