[2018.09.12 T1] 下落的圆盘

解决一个几何放置问题,要求在限定区域内放置多个不相交的圆形,通过随机算法找到可行解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

暂无链接

下落的圆盘

题目描述

有n个圆盘从天而降! 虽然后面落下的可以盖住前面落下的,可是天神
小O觉得这样很不美观,于是他规定:所有的圆盘两两不能相交!(可以相
切)当然,陆地的大小是有限制的,具体的说,每个圆盘的圆心的x坐标必须
在[0, W]以内,y坐标必须在[0, L]以内。

天神小O想要你帮他构造一个方案。当然,因为他觉得你非常naive,他做
出了一点限制:所有圆盘的面积和不超过15WL15WL

输入格式

第一行有三个整数:n, W, L。

第二行有n个整数,分别表示n个圆盘的半径。

输出格式

输出n行,每行2个实数,表示第i个圆盘的圆心位置。

样例输入

2 6 6
1 1

样例输出

0.0 0.0
6.0 6.0

数据范围与约定

1W,L1091≤W,L≤109

1ri1051≤ri≤105

5×π×(ni=1r2i)w×L5×π×(∑i=1nri2)≤w×L

对于40%40% 的数据,1n101≤n≤10

对于100%100%的数据,1n1031≤n≤103

题目保证有解。

在检验答案合法性时,如果两个实数的差小于10610−6,我们认为它们相等。

题解

考场上写了个模拟退火,居然有7070分,觉得自己很强,结果人家直接randrand就能过。。。

正解是非常暴力的乱搞,大概可能是先按半径从大到小排个序,然后就一直randrand,直到合法。。。

1.gif

代码
#include<bits/stdc++.h>
#define db double
#define eps 1e-6
#define random(i) cir[i].x=rand()%(w+1),cir[i].y=rand()%(l+1)
using namespace std;
const int M=1005;
struct sd{db x,y,r,id;}cir[M];
bool cmp1(sd a,sd b){return a.r>b.r;}
bool cmp2(sd a,sd b){return a.id<b.id;}
int n,w,l;
db sqr(db x){return x*x;}
db dis(sd a,sd b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
bool check(int x){for(int i=1;i<x;++i)if(dis(cir[i],cir[x])<cir[i].r+cir[x].r-eps)return 1;return 0;}
void in(){scanf("%d%d%d",&n,&w,&l);for(int i=1;i<=n;++i)scanf("%lf",&cir[i].r),cir[i].id=i;}
void ac()
{
    sort(cir+1,cir+1+n,cmp1);cir[1].x=cir[1].y=0;
    for(int i=2;i<=n;++i)for(random(i);check(i);random(i));
    sort(cir+1,cir+1+n,cmp2);
    for(int i=1;i<=n;++i)printf("%.1lf %.1lf\n",cir[i].x,cir[i].y);
}
int main(){in();ac();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值