隨機化初步

/*
隨機化初步
只看了一下午加一夜 可能理解的不到位
簡單說一下就是在一些狀況下咱們每次隨機的機率^隨機的次數≈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;
}
相關文章
相關標籤/搜索