随机化初步

/*
随机化初步
只看了一下午加一晚上 可能理解的不到位
简单说一下就是在一些情况下我们每次随机的概率^随机的次数≈1
关键是想清楚是不是≈1 然后看题 
emmmmmm "我什么都不会,我连搜题目都不会"
下午找了几道随机化的题目
第一道 POJ    3318 暴力也能水过去 
而且随机化比较好像 而且poj GG了
第二道 暴力题就是 然后博主觉得随机化好玩就写了一发
终于找到一个比较适合随机化入门的题目
Hdu 6242
题意 找一个点一个半径确定一个圆,使得给出的n个点有一半以上在这个圆上
每次随机的找3个点确定一个圆  看看这个圆合不合法
每次这三个都在答案圆上的概率是1/8 然后我们随机1000次 几乎一定能随机到答案圆
然后有一些坑
1.n<=4要特判 因为可能找不到3点不共线
2.精度为题,虽然要求3位小数,然后只要是个double就不能用==
3.*******特判的时候输出记得加回车(类似的打Case:**)
4.题目条件读全 半径和点左边小于1e9 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#define maxn 100010
using namespace std;
int T,n;
double R;
struct node{
    double x,y;
}A[maxn];
node Get_p(node p1,node p2,node p3){
    double a,b,c,d,e,f;node p;
    a=2*(p2.x-p1.x);
    b=2*(p2.y-p1.y);
    c=p2.x*p2.x+p2.y*p2.y-p1.x*p1.x-p1.y*p1.y;
    d=2*(p3.x-p2.x);
    e=2*(p3.y-p2.y);
    f=p3.x*p3.x+p3.y*p3.y-p2.x*p2.x-p2.y*p2.y;
    p.x=(b*f-e*c)/(b*d-e*a);
    p.y=(d*c-a*f)/(b*d-e*a);
    R=(p.x-p1.x)*(p.x-p1.x)+(p.y-p1.y)*(p.y-p1.y);
    return p;
}
bool Ok(node p1,node p2,node p3){
    return (p1.y-p2.y)*(p2.x-p3.x)==(p2.y-p3.y)*(p1.x-p2.x);
}
double Cal(node i,node j){
    return (i.x-j.x)*(i.x-j.x)+(i.y-j.y)*(i.y-j.y);
}
double Abs(double x){
    return x>0?x:-x;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&A[i].x,&A[i].y);
        if(n==1){
            printf("%lf %lf %lf\n",A[1].x-1,A[1].y,1.0);continue;
        }
        if(n<=4){
            printf("%lf %lf %lf\n",(A[1].x+A[2].x)/2,(A[1].y+A[2].y)/2,sqrt(Cal(A[1],A[2]))/2);continue;
        }
        for(int k=1;k<=1000;k++){
            int x=rand()%n+1;
            int y=rand()%n+1;
            while(y==x)y=rand()%n+1;
            int z=rand()%n+1;
            while(z==y||z==x||Ok(A[x],A[y],A[z]))
                z=rand()%n+1;
            node p=Get_p(A[x],A[y],A[z]);
            if(Abs(p.x)>1e9||Abs(p.y)>1e9||Abs(sqrt(R))>1e9)continue;
            int sum=0;for(int i=1;i<=n;i++)
                if(Abs(Cal(A[i],p)-R)<1e-6)sum++;
            if(sum>=(n+1)/2){
                printf("%lf %lf %lf\n",p.x,p.y,sqrt(R));break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yanlifneg/p/9568821.html