暂无链接
下落的圆盘
题目描述
有n个圆盘从天而降! 虽然后面落下的可以盖住前面落下的,可是天神
小O觉得这样很不美观,于是他规定:所有的圆盘两两不能相交!(可以相
切)当然,陆地的大小是有限制的,具体的说,每个圆盘的圆心的x坐标必须
在[0, W]以内,y坐标必须在[0, L]以内。
天神小O想要你帮他构造一个方案。当然,因为他觉得你非常naive,他做
出了一点限制:所有圆盘的面积和不超过
15WL
1
5
W
L
。
输入格式
第一行有三个整数:n, W, L。
第二行有n个整数,分别表示n个圆盘的半径。
输出格式
输出n行,每行2个实数,表示第i个圆盘的圆心位置。
样例输入
2 6 6
1 1
样例输出
0.0 0.0
6.0 6.0
数据范围与约定
1≤W,L≤109 1 ≤ W , L ≤ 10 9
1≤ri≤105 1 ≤ r i ≤ 10 5
5×π×(∑ni=1r2i)≤w×L 5 × π × ( ∑ i = 1 n r i 2 ) ≤ w × L
对于 40% 40 % 的数据, 1≤n≤10 1 ≤ n ≤ 10 。
对于 100% 100 % 的数据, 1≤n≤103 1 ≤ n ≤ 10 3 。
题目保证有解。
在检验答案合法性时,如果两个实数的差小于 10−6 10 − 6 ,我们认为它们相等。
题解
考场上写了个模拟退火,居然有 70 70 分,觉得自己很强,结果人家直接 rand r a n d 就能过。。。
正解是非常暴力的乱搞,大概可能是先按半径从大到小排个序,然后就一直 rand r a n d ,直到合法。。。
代码
#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();}