随机化贪心

在说随机化贪心前先说一下随机数据生成。

随机数据生成

头文件ctime,cstdlib。
调用函数 rand(),srand(),其中注意windows中RAND_MAX=32767。
rand()返回0~RAND_MAX之间随机整数。
srand()初始化rand()种子。

    srand((unsigned)time(0));
    (long long)rand()\RAND_MAX*n  //n自己定义。

随机化贪心

先rand()一组数,对其处理使其在题目范围内,在按照题目要求对其进行判断,若可以则直接输出,return 0;若不行则从新rand(),直到可以为止。

例题

luogu5月月赛T2

题目描述

Alice 和 Bob 生活在一个l*l的正方形房子里,由于 Bob 最近沉迷隔膜,Alice 决定要限制 Bob 上网的频率。
Alice 建造了 n个无线信号屏蔽器,第i个位于 (xi,yi),屏蔽范围为 l/n.
Bob 网瘾发作按捺不住上网的冲动,找到了你,帮他找到一个位置(x,y),使得没有被 Alice 的无线信号屏蔽器覆盖。
输入输出格式

输入格式:

第一行两个整数 n,l(1≤n≤10,1≤l≤1e5),分别表示无线信号屏蔽器的个数和房子的大小。
接下来n行,每行2个数,分别是 xi,y(0≤xi​,yi​≤l) ,意义如上所述。

输出格式:

如果可以找到,输出两个数 x,y(0≤x,y≤l)x, y(0 \leq x, y \leq l)x,y(0≤x,y≤l) ,意义如上所述,如果有多组解,输出任意一组即可。如果你输出的解满足到任意一个屏蔽器的距离都不小于 ln+10−6\frac{l}{n} + 10^{-6}n
l​+10−6 ,则视为正确。
否则输出 “GG”。
输入输出样例
输入样例#1:
1 1
0.000 0.000
输出样例#1:
0.999 0.999

输入样例#2:
1 2
1.000 1.000
输出样例#2:
GG

输入样例#3
2 2
0.000 0.000
2.000 2.000
输出样例#3:
1.000 1.000

分析

如果n=1,则枚举一下四个角,如果都不可行,一定无解,否则就找到了合法点。
如果n≥2,则圆的总面积一定小于正方形的面积,每次随机一个点,判断是否可行。
上代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
double x[11],y[11],ax,ay,t;
bool flag=0;
inline int read(){
    int ret=0;
    char c=getchar();
    bool flag=false;
    while(c<'0'||'9'<c){
        if(c=='-') flag=true;
        c=getchar();
    }
    while('0'<=c&&c<='9') ret=ret*10+c-'0',c=getchar();
    return flag?-ret:ret;
}
double dist(double a,double b,double c,double d){
    return (double)sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
inline void work(){
    int aa=rand()%(n*100),bb=rand()%(n*100);
    double a=(double)aa/100,b=(double)bb/100;
    for (register int i=1;i<=m;i++){
        double d=dist(a,b,x[i],y[i]);
        if (d<=t+1e-9) return ;
    }
    printf("%.3lf %.3lf\n",a,b);
    flag=1;
}
int main(){
    srand(time(0));
    m=read(),n=read();
    t=n/m;
    for(register int i=1;i<=m;i++)
        scanf("%lf%lf",&x[i],&y[i]);
    if(t> sqrt(2)*n){
        printf("GG\n");
        return 0;
    }
    int T=100000;
    while(T--){
        work();
        if(flag) return 0;
    }
    cout<<"GG";
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值