题目链接:https://vjudge.net/problem/HDU-2469
题目大意:给你n个点,要求你找出面积最小的扇形,使得这个扇形覆盖这n个点中的k个点,输出这个扇形的面积。
思路:枚举每一个点,找出半径等于这个点到原点距离的最小扇形,覆盖k个点,为了避免一些比较刁钻的角度(纯粹是为了代码好写),将所有点复制一下并且角度加,在计算扇形是否包括k个点时可使用双端队列,当头尾点相同时结束循环。时间复杂度。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e3+5;
const double pi=acos(-1);
class point
{
public:
int x,y;
int len;
double jiao;
point(){}
point(int x,int y):x(x),y(y),len(x*x+y*y)
{
jiao=atan2(y,x);
}
bool operator < (const point other)const
{
return jiao<other.jiao;
}
};
bool operator == (const point a,const point b)
{
return a.x==b.x&&a.y==b.y;
}
point input[MAXN*2];
int main()
{
#ifdef ZYP
freopen("hdu-2469.01.inp","r",stdin);
#endif
int n,k;
int cas=1;
while(scanf("%d%d",&n,&k),n)
{
printf("Case #%d: ",cas++);
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
input[i]=point(x,y);
}
if(k<=1)
{
printf("0.00\n");
continue;
}
sort(input,input+n);
for(int i=0;i<n;i++){input[i+n]=input[i];input[i+n].jiao+=2*pi;}
double ans=1e100;
for(int i=0;i<n;i++)
{
int len=input[i].len;
int cnt=0;
for(int j=0;j<n;j++)if(input[j].len<=len)cnt++;
if(cnt<k)continue;
deque<point>q;
double jiao=10*pi;
for(int j=0;j<n*2;j++)
{
if(q.size()==k)
{
jiao=min(jiao,q.back().jiao-q.front().jiao);
}
if(q.size()>1&&q.front()==q.back())break;
if(input[j].len<=len)q.push_back(input[j]);
if(q.size()>k)q.pop_front();
}
if(q.size()==k)
{
jiao=min(jiao,q.back().jiao-q.front().jiao);
}
ans=min(ans,jiao*len/2);
}
printf("%.2f\n",ans);
}
return 0;
}
反思:感觉最近做题的时候思路都被局限了,总想着时间复杂度 的代码肯定过不了,然后这题朝着的方向想了好久都没思路,以后要注意。