spoj 145 Aliens(增量法+最小包围圈)
来源:互联网 发布:网络词爸爸是什么意思 编辑:程序博客网 时间:2024/04/24 12:02
【题目大意】:给出你T个case。每个case有n个点,叫你求这个点的半径和圆心坐标,使得这个圆覆盖所有的点(n<=100000)
【解题思路】:曾经在zoj上做过一道最小圆的覆盖,但是那道题的点只有100,当初是暴力做的。显然碰到这个数据量是行不通的,我们可以采取dfs进行增量,或者利用随机重排进行增量,二者在spoj上测试的时间差距不大,网络模版testing。
【代码】:
dfs实现增量
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip> using namespace std; #define eps 1e-8#define pi acos(-1.0)#define inf 1<<30#define linf 1LL<<60#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long longint n;struct Point{ double x; double y;}pt[1005];struct Traingle{ struct Point p[3];};struct Circle{ struct Point center; double r;}ans;//计算两点距离double Dis(struct Point p, struct Point q){ double dx=p.x-q.x; double dy=p.y-q.y; return sqrt(dx*dx+dy*dy);}//计算三角形面积double Area(struct Traingle ct){ return fabs((ct.p[1].x-ct.p[0].x)*(ct.p[2].y-ct.p[0].y)-(ct.p[2].x-ct.p[0].x)*(ct.p[1].y-ct.p[0].y))/2.0;}//求三角形的外接圆,返回圆心和半径(存在结构体"圆"中)struct Circle CircumCircle(struct Traingle t){ struct Circle tmp; double a,b,c,c1,c2; double xA,yA,xB,yB,xC,yC; a=Dis(t.p[0],t.p[1]); b=Dis(t.p[1],t.p[2]); c=Dis(t.p[2],t.p[0]); //根据S = a * b * c / R / 4;求半径R tmp.r=(a*b*c)/(Area(t)*4.0); xA=t.p[0].x; yA=t.p[0].y; xB=t.p[1].x; yB=t.p[1].y; xC=t.p[2].x; yC=t.p[2].y; c1=(xA*xA+yA*yA-xB*xB-yB*yB)/2; c2=(xA*xA+yA*yA-xC*xC-yC*yC)/2; tmp.center.x=(c1*(yA-yC)-c2*(yA-yB))/((xA-xB)*(yA-yC)-(xA-xC)*(yA-yB)); tmp.center.y=(c1*(xA-xC)-c2*(xA-xB))/((yA-yB)*(xA-xC)-(yA-yC)*(xA-xB)); return tmp;}//确定最小包围圆struct Circle MinCircle(int num, struct Traingle ct){ struct Circle ret; if (num==0) ret.r=0.0; else if (num==1){ ret.center=ct.p[0]; ret.r = 0.0; } else if (num==2){ ret.center.x=(ct.p[0].x+ct.p[1].x)/2.0; ret.center.y=(ct.p[0].y+ct.p[1].y)/2.0; ret.r=Dis(ct.p[0], ct.p[1])/2.0; } else if(num==3) ret=CircumCircle(ct); return ret;}//递归实现增量算法void Dfs(int x, int num, struct Traingle ct){ int i, j; struct Point tmp; ans = MinCircle(num, ct); if (num==3) return; for (i=1; i<=x; i++) if (Dis(pt[i],ans.center)>ans.r){ ct.p[num]=pt[i]; Dfs(i-1,num+1,ct); tmp=pt[i]; for (j=i; j>=2; j--) pt[j]=pt[j-1]; pt[1]=tmp; }}void Solve(int n){ struct Traingle ct; Dfs(n,0,ct);}int main(){ int T; cin >> T; while (T--){ scanf("%d",&n); if (n==0) break; for (int i=1; i<=n; i++) scanf("%lf %lf",&pt[i].x,&pt[i].y); Solve(n); printf("%.2f\n",ans.r); printf("%.2f %.2f\n",ans.center.x,ans.center.y); } return 0;}
随机重排增量
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip> using namespace std; #define eps 1e-10#define pi acos(-1.0)#define inf 1<<30#define linf 1LL<<60#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long longconst int N=100010;int n;struct cpoint { double x, y;}cp[N];int dcmp(double x) { if (x < -eps) return -1; else return x > eps;}double sqr(double x) { return x * x; }double dis(cpoint p1,cpoint p2) { return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}void center(cpoint p0, cpoint p1, cpoint p2, cpoint &cp) { //三角形外心 double a1=p1.x-p0.x,b1=p1.y-p0.y,c1=(sqr(a1)+sqr(b1))/2; double a2=p2.x-p0.x,b2=p2.y-p0.y,c2=(sqr(a2)+sqr(b2))/2; double d=a1*b2-a2*b1; cp.x=p0.x+(c1*b2-c2*b1)/d; cp.y=p0.y+(a1*c2-a2*c1)/d;}void MinCir(cpoint cp[], int n, cpoint &c, double &r) { random_shuffle(cp, cp + n); c = cp[0]; r = 0; for (int i = 1; i < n; ++i) { if (dcmp(dis(cp[i], c) - r) <= 0) continue; c = cp[i]; r = 0; for (int j = 0; j < i; ++j) { if (dcmp(dis(cp[j], c) - r) <= 0) continue; c.x = (cp[i].x + cp[j].x) / 2; c.y = (cp[i].y + cp[j].y) / 2; r = dis(c, cp[j]); for (int k = 0; k < j; ++k) { if (dcmp(dis(cp[k], c) - r) <= 0) continue; center(cp[i], cp[j], cp[k], c); r = dis(c, cp[k]); } } }}void solve() { scanf("%d",&n); for (int i=0; i<n; ++i) { scanf("%lf%lf",&cp[i].x,&cp[i].y); } cpoint c; double r; MinCir(cp,n,c,r); printf("%.2f\n%.2f %.2f\n",r,c.x,c.y);}int main() { int T; cin >> T; while (T--) { solve(); } return 0;}
- spoj 145 Aliens(增量法+最小包围圈)
- 【SPOJ-ALIEN2】Aliens at the train, again!【DP】
- SPOJ 1693 Coconuts 最小割
- spoj 839 最小割应用
- spoj 839 最小割+二进制
- SPOJ Optimal Marks 最小割
- SPOJ PHT【二分】+SPOJ INUM【最小/大值重复】
- [SPOJ 839]Optimal Marking(最小割)
- SPOJ 839 Optimal Marks 最小割
- SPOJ 371 Boxes 最小费用流
- 【SPOJ】839 Optimal Marks 最小割
- SPOJ 104 Highways 最小生成树计数
- spoj COCONUTS (最小割模型)
- SPOJ 297 Aggressive cows 最小间隔
- SPOJ Optimal Marks(最小割的应用)
- 2400: Spoj 839 Optimal Marks 最小割
- 【bzoj2400】Spoj 839 Optimal Marks 最小割
- 【SPOJ-SCPC11H】Dolls【最小路径覆盖】
- 开始工作后,一个人会失去什么?
- sdsa
- 学习正则表达式(2012-4-11)
- 运算器的发展
- 聊天随想
- spoj 145 Aliens(增量法+最小包围圈)
- 网页演示注意事项2012410
- 数据库之【PL SQL块 与 控制结构举例】
- 一个有意思的C++问题,应该是面试题吧。
- 微创新
- 【Android 安卓】腾讯推出安卓4.0 ROM:Tita
- 使用trac进行项目管理
- 设置文件的访问权限
- Fedora16为grub2添加、修改背景图片和字体颜色