可变的圆 二分?排序?
来源:互联网 发布:html时间轴 demo 源码 编辑:程序博客网 时间:2024/05/19 21:41
问题源自ACM-ICPC 北京赛区2015网络赛题目1 : The Cats' Feeding Spots
大意是这样的,给出m个点,选其中一个点作为圆心画一个圆能把n个点包含在里面(边界不能有点),求最小的半径,找不到这样的半径输出-1。
自己最开始的思路是这样的,以其中一个点作为圆心,然后用伪二分法查找半径(初始化 low=1,high=1416。1000*2^0.5=1414.213),因为毕竟不是高效正统的二分,所以暂时叫它伪二分吧。
是的,感觉有点乱,而且时间用了800ms。我看了一份更加优秀的代码,它的思路大致是这样,找圆心的部分也是普通的循环遍历,查找最小半径:对于每一个圆心都计算出它和别的点的距离,然后使用快速排序:
for(int j=0;j<m;j++){
dis[j]=sqrt((data[j].x-data[i].x)*(data[j].x-data[i].x)+(data[j].y-data[i].y)*(data[j].y-data[i].y));
}
sort(dis,dis+m);
包含n个点的半径应该就是(int)dis[n-1]+1,用ans保存最小的值最后输出结果(不贴代码了,没有别人的许可)。我的做法有许多的修正工作,所以计算次数是100*max(log2(100),100)*100,后者的计算是100*100*(log2(100),优劣很快就能区分开。总之,提升水平。。。
大意是这样的,给出m个点,选其中一个点作为圆心画一个圆能把n个点包含在里面(边界不能有点),求最小的半径,找不到这样的半径输出-1。
自己最开始的思路是这样的,以其中一个点作为圆心,然后用伪二分法查找半径(初始化 low=1,high=1416。1000*2^0.5=1414.213),因为毕竟不是高效正统的二分,所以暂时叫它伪二分吧。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int maxn=105;int n,m;struct node{ double x,y;}p[maxn];int r[maxn];double dis(node a,node b){ return fabs(sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));}int in(int dex,int d){ int res=0; double dd=d*1.0; for(int i=0;i<m;i++){ if(dd-dis(p[dex],p[i])>1e-6) res++; } return res;}int mf(int dex){ int low=1,high=1416,mid; //1000*2^0.5=1415 while(low<=high){ mid=(low+high)/2; int sum=in(dex,mid); if(sum>=n) high=mid-1; else return mid; } return mid;}int main(){ //freopen("cin.txt","r",stdin); int t; cin>>t; while(t--){ scanf("%d%d",&m,&n); memset(r,-1,sizeof(r)); for(int i=0;i<m;i++){ scanf("%lf%lf",&p[i].x,&p[i].y); } for(int i=0;i<m;i++){ int w=mf(i); if(in(i,w)==n) r[i]=w; while(r[i]==-1&&w<=1415){ w++; if(in(i,w)==n) break; } if(r[i]==-1)r[i]=w; for(int j=0;j<m;j++){ if(fabs(dis(p[i],p[j])-r[i])<1e-6) { r[i]=-1; break; } } } int ans=2000; for(int i=0;i<m;i++){ if(r[i]<=1415&&r[i]>=1)ans=min(ans,r[i]); } if(ans>1415)puts("-1"); else printf("%d\n",ans); } return 0;}
是的,感觉有点乱,而且时间用了800ms。我看了一份更加优秀的代码,它的思路大致是这样,找圆心的部分也是普通的循环遍历,查找最小半径:对于每一个圆心都计算出它和别的点的距离,然后使用快速排序:
for(int j=0;j<m;j++){
dis[j]=sqrt((data[j].x-data[i].x)*(data[j].x-data[i].x)+(data[j].y-data[i].y)*(data[j].y-data[i].y));
}
sort(dis,dis+m);
包含n个点的半径应该就是(int)dis[n-1]+1,用ans保存最小的值最后输出结果(不贴代码了,没有别人的许可)。我的做法有许多的修正工作,所以计算次数是100*max(log2(100),100)*100,后者的计算是100*100*(log2(100),优劣很快就能区分开。总之,提升水平。。。
0 0
- 可变的圆 二分?排序?
- 51NOD 1278 相离的圆(二分 + 排序)
- 51nod 1278 相离的圆 二分+排序
- 二分排序
- 二分排序
- 二分排序
- 二分排序
- 二分排序
- 排序+二分
- 二分排序
- 二分排序
- 二分排序
- 插入排序的二分查找策略
- 简单的快速排序与二分查找
- 字符串的快速排序和二分查找
- 对排序的总结&&二分查找
- 快速排序以及二分查找的实现
- 同事写的二分归并排序
- 线性表概念
- Docker命令行探秘
- andriod PullToRefresh的使用 构建下拉刷新的listView
- ORA-00257: archiver error. Connect internal only, until freed 归档日志满处理方法
- java SE复习笔记28
- 可变的圆 二分?排序?
- UVA 11136 Hoax or what(Multiset)
- 技术人生:故事之四十五谁明白为什么信息化
- 技术人生:故事之四十六互联网络给了我们什么
- getParameter与getAttribute的区别
- nnoDB引擎类型支持外键约束
- 利用 fastjson.jar 把对象解析成Json 数据
- 解决myeclipse10.x的Servers产生的at com.genuitec.eclipse.ast.deploy.core.Deployment.<init>(Unknown Source)错
- 软件测试复习要点