hdu 3511

来源:互联网 发布:完整的数据库源代码 编辑:程序博客网 时间:2024/06/05 07:23

  题目意思实际上就是找嵌套数最大的圆并输出其嵌套数。

  一开始见时间有5000ms,就果断暴力,然后果断超时— — 之后用二分,终于不tle啦,但wa。。。TAT。上网找题解,发现有两种方法,一个是用随机数,另一个是计算几何中的扫描法,其中用了set,没见过,于是好好学习了一下,发现思想还是很好懂的,该解法的所在地址是:

http://hi.baidu.com/bobobry/blog/item/e270bf097b3bd9376b60fbbe.html

 

以下是计算几何的解法:

 

#include<cstdio>#include<cstring>#include<stdlib.h>#include<set>#include<cmath>using namespace std;const int M=50100;int max(int a,int b) {return a>b?a:b;}int n,t;struct cirs{ int x,y; int r,w;}cir[M];struct event{ int x; int id,mark;   //mark为1,则圆为运算对象,反之,圆要删出set}eve[2*M];int nowx;double cacul(int id,int mark){ double d; d=sqrt((double)cir[id].r*cir[id].r-(double)(nowx-cir[id].x)*(nowx-cir[id].x)); return mark?(double)cir[id].y+d:(double)cir[id].y-d;}bool equal(double a,double b){ if(fabs(a-b)<1e-8) return 1; else return 0;}struct nodes{ int id; int mark; bool operator<(const nodes a)const   //set的<要重载 {  double y1=cacul(id,mark);  double y2=cacul(a.id,a.mark);  return y1>y2 || equal(y1,y2) && mark>a.mark; }};set<nodes> line;set<nodes>::iterator it,pre,succ;int cmp(const void *a,const void *b){ int t; struct event *x,*y; x=(struct event *)a; y=(struct event *)b; t=x->x-y->x; if(t!=0) return t; else t=cir[y->id].y-cir[x->id].y; return t;}void move_line()     //计算几何中的扫描法{ line.clear(); int i,j; for(i=0;i<t;i++) {  nowx=eve[i].x;  if(eve[i].mark==1)    //这个圆没运算过  {   struct nodes node;   node.id=eve[i].id;   node.mark=1;   it=line.insert(node).first;   succ=pre=it;   succ++;   if(it==line.begin() || succ==line.end())   {    cir[it->id].w=1;           //此时是最外层的圆   }   else               //当前圆嵌套与前一个圆中   {    pre--;    if(pre->id==succ->id)    {     cir[it->id].w=cir[pre->id].w+1;    }    else           //处于同一嵌套级别的圆的嵌套数    {     cir[it->id].w=max(cir[pre->id].w,cir[succ->id].w);    }   }   struct nodes node2;   node2.id=eve[i].id;   node2.mark=0;   line.insert(node2).second;  }  else              //该圆的右点以被扫描到,该离开set了  {   struct nodes node,node2;   node.id=eve[i].id;   node.mark=1;   line.erase(node);   node2.mark=0;   node2.id=eve[i].id;   line.erase(node2);  } }}int main(){// freopen("in.txt","r",stdin); int i,j; while(scanf("%d",&n)==1) {  t=0;  for(i=0;i<n;i++)  {   scanf("%d%d%d",&cir[i].x,&cir[i].y,&cir[i].r);   cir[i].w=0;   eve[t].x=cir[i].x-cir[i].r;   eve[t].id=i;   eve[t].mark=1;   t++;   eve[t].x=cir[i].x+cir[i].r;   eve[t].id=i;   eve[t].mark=0;   t++;  }  qsort(eve,t,sizeof(eve[0]),cmp);  move_line();  int ans=-1;  for(i=0;i<n;i++)  {   if(cir[i].w>ans)    ans=cir[i].w;  }  printf("%d\n",ans); } return 0;}


 

接下的这份随机函数的代码就真的很考验rp的哈,我交了8次才过了3次。。。两次是直接拿那位大牛的来交的。。。。

 

#include<cstdio>#include<cstring>#include <cstdlib>#include<ctime>#include<iostream>using namespace std;const int M=50000;struct cir{ double x,y,r;}c[M];bool vis[M];int n;int main(){ srand((unsigned)time(NULL)); while(scanf("%d",&n)==1) {  int i,j,ans=-1;  for(i=0;i<n;i++)   scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);  memset(vis,0,sizeof(vis));  int tmp=1;  for(j=1;j<n;j++)  {   if((c[0].x-c[j].x)*(c[0].x-c[j].x)+(c[0].y-c[j].y)*(c[0].y-c[j].y)<c[j].r*c[j].r)    tmp++;  }  if(tmp>ans) tmp=ans;  int rd;  for(i=0;i<n && i<5000 && ans!=n;)  {   rd=rand()%n;   if(vis[rd]) continue;   vis[rd]=1;   i++;   tmp=1;   for(j=0;j<n;j++)   {    if(rd==j) continue;    if((c[rd].x-c[j].x)*(c[rd].x-c[j].x)+(c[rd].y-c[j].y)*(c[rd].y-c[j].y)<c[j].r*c[j].r)     tmp++;   }   if(tmp>ans) ans=tmp;  }  printf("%d\n",ans); } return 0;}

原创粉丝点击