HDU 5531 Rebuild (2015长春现场赛,计算几何+三分法)
Rebuild
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 521 Accepted Submission(s): 125
The ruins form a closed path on an x-y plane, which has n endpoints. The endpoints locate on (x1,y1), (x2,y2), …,(xn,yn) respectively. Endpoint i and endpointi−1 are adjacent for 1<i≤n, also endpoint 1 and endpoint n are adjacent. Distances between any two adjacent endpoints are positive integers.
To rebuild, they need to build one cylindrical pillar at each endpoint, the radius of the pillar of endpoint i is ri. All the pillars perpendicular to the x-y plane, and the corresponding endpoint is on the centerline of it. We call two pillars are adjacent if and only if two corresponding endpoints are adjacent. For any two adjacent pillars, one must be tangent externally to another, otherwise it will violate the aesthetics of Ancient ACM Civilization. If two pillars are not adjacent, then there are no constraints, even if they overlap each other.
Note that ri must not be less than 0 since we cannot build a pillar with negative radius and pillars with zero radius are acceptable since those kind of pillars still exist in their neighbors.
You are given the coordinates of n endpoints. Your task is to find r1,r2,…,rn which makes sum of base area of all pillars as minimum as possible.

For example, if the endpoints are at (0,0), (11,0), (27,12), (5,12), we can choose (r1, r2, r3, r4)=(3.75, 7.25, 12.75, 9.25). The sum of base area equals to 3.752π+7.252π+12.752π+9.252π=988.816…. Note that we count the area of the overlapping parts multiple times.
If there are several possible to produce the minimum sum of base area, you may output any of them.
The first line of each case contains one positive integer n, the size of the closed path. Next n lines, each line consists of two integers (xi,yi) indicate the coordinate of the i-th endpoint.
1≤t≤100
3≤n≤104
|xi|,|yi|≤104
Distances between any two adjacent endpoints are positive integers.
If there are several possible ways to produce the minimum sum of base area, you may output any of them.
4
0 0
11 0
27 12
5 12
5
0 0
7 0
7 3
3 6
0 6
5
0 0
1 0
6 12
3 16
0 12
3.75
7.25
12.75
9.25
157.08
6.00
1.00
2.00
3.00
0.00
IMPOSSIBLE
【题意】:
给出一个N边形的顶点和边长,对于每个顶点作一圆,要求邻接顶点对应的两圆外切(不相邻顶点无要求)。找出一组Ri(R>=0)使得所有圆的面积和最小。
【解题思路】:
由于邻接点对应的圆要外切,则确定一个圆的半径r后,即可唯一确定所有圆的半径(Ri = di - Ri-1);设连接点 1 与 n 的边为 d1,以此类推。则必须满足 R1 + Rn = d1。根据此关系可以得到一个关于r与d的等式。
化简容易看出:
①当 n 为奇数时,可行的 r 可以唯一确定,r = d1+ (d2+…+d(2n)) - (d3+…+d(2n+1));
②当 n 为偶数时,必定满足 d1+d3+d5+… = d2+d4+d6+…,否则IMPOSSIBLE(仅为必要条件)
此时 S = r1^2 + … +rn^2 = ax^2+bx+c 为一个二次函数表达式。
用 r 来表示Ri,首先可计算出a b c. 再根据每 ri <= di 这个关系求出r的取值范围[low, high].(无范围则IMPOSSIBLE)
有了二次函数表达式和自变量范围,用三分法求出半径平方和取最小值时的 r .
根据①②求出的 r ,计算出所有的Ri,再依次判断每个Ri是否非负。
注意精度问题(坑点!):
由于本题只保留2位小数,计算面积和时,若用 S = Sum(pi*r*r)计算则会出现精度问题(具体解释不清、亲测会挂),须在括号外乘PI,即 S = pi * Sum(r*r).
现场这题过得不多,封榜时一口气打完交了2发WA,当时感觉思路非常清晰正确,不知道从哪调起,不停换机位到最后也没过。
当时怨念很深,把代码打印带了回来查个究竟。先是在某论坛看到有人说精度这个坑,后来HDU重现赛再打,发现一个重大且傻逼的错误,当时求出二次函数后,以为最低点(-b/2a)如果取不到则IMPOSSIBLE当时想了三分以为跟这个是一样的),但显然要根据 r 的取值范围用三分法来逼近最小值。
长春打铁很遗憾,第一次参加 ICPC 区域赛,既有遗憾也有教训。归根结底还是自己太弱,而且还不好好训练。明年就大三了,有了这次教训,接下来一年一定要好好训练好好总结,争取早日取得成绩。同时,stark 目前也还有各方面欠缺,希望能跟队友共勉,一起努力。
Upd 15.11.6 合肥赛前总结下长春得失,希望合肥站加油!(默默感谢队友wqp让出这个机会).
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 1e-8
#define PI acos(-1.0)
#define LL long long
#define maxn 100100
#define IN freopen("in.txt","r",stdin);
using namespace std; struct Point {
double x,y;
}; int sign(double x) {
if(fabs(x)<eps) return ;
return x<? -:;
} double Distance(Point p1,Point p2) {
return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
} int n;
Point p[maxn];
double d[maxn]; int check(double r)
{
if(sign(r) < ) return ; for(int i= ;i<=n; i++) {
r = d[i]-r;
if(sign(r) < ) return ;
}
return ;
} /*三分法求面积最小时的r*/
double a,b,c;
double cal(double x) {
return a*x*x + b*x + c;
} double solve(double low, double high)
{
while(high-low > eps){
double mid = (high+low)/2.0;
double midmid = (mid+high)/2.0;
if(sign(cal(midmid)-cal(mid)) > ) high = midmid;
else low = mid;
} return low;
} int main(int argc, char const *argv[])
{
//IN; int t;scanf("%d",&t);
while(t--)
{
double r = ;
memset(p, , sizeof(p));
memset(d, , sizeof(d));
int flag = ; scanf("%d", &n);
for(int i= ;i<=n; i++)
scanf("%lf %lf", &p[i].x, &p[i].y);
d[]=Distance(p[], p[n]);
for(int i=; i<=n; i++)
d[i] = Distance(p[i], p[i-]); if(n% != ){
r = d[];
for(int i=; i<=n; i++){
if(i% == ) r += d[i];
else r -= d[i];
}
r /= 2.0;
flag = check(r);
} else{
double tmp = ;
for(int i=; i<=n; i++){
if(i% != ) tmp += d[i];
else tmp -= d[i];
}
if(sign(tmp) != ) {flag=; goto end;} /*半径平方和的二次表达式*/
a=1.0; b=; c=;
tmp = ;
for(int i=; i<=n; i++){
a += 1.0;
tmp = d[i]-tmp;
c += tmp*tmp;
if(i% == ) b -= 2.0*tmp;
else b += 2.0*tmp;
} /*
错误地以为最低点为唯一取值点,若最低点不符合则无解.
r=(-b)/(2.0*a);
if(sign(r)<0) r=0;
flag = check(r);
*/ /*检查每条边计算三分时r的可行范围*/
double low=, high = d[];
tmp = ;
for(int i=; i<=n; i++){
if(i% == ){
tmp += d[i];
high = min(high, tmp);
}
else{
tmp -= d[i];
low = max(low, tmp);
}
} if(low > high) flag = ;
else{
r = solve(low, high);
flag = check(r);
}
} end:
if(!flag) printf("IMPOSSIBLE\n");
else{
double R[maxn];
R[]=r;
double temp = ;
for(int i=; i<=n; i++){
temp = d[i]-R[i-];
R[i] = temp;
}
double ans = ;
for(int i=; i<=n; i++){
//ans += R[i]*R[i]*PI;精度问题
ans += R[i]*R[i];
} printf("%.2lf\n", ans*PI);
for(int i=; i<=n; i++){
printf("%.2lf\n", R[i]);
}
} } return ;
}
HDU 5531 Rebuild (2015长春现场赛,计算几何+三分法)的更多相关文章
- HDU 5512 Pagodas (2015沈阳现场赛,找规律+gcd)
Pagodas Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- HDU 5510 Bazinga (2015沈阳现场赛,子串判断)
Bazinga Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- hdu 5441 Travel (2015长春网赛)
http://acm.hdu.edu.cn/showproblem.php?pid=5441 题目大意是给一个n个城市(点)m条路线(边)的双向的路线图,每条路线有时间值(带权图),然后q个询问,每个 ...
- hdu 5441 (2015长春网络赛E题 带权并查集 )
n个结点,m条边,权值是 从u到v所花的时间 ,每次询问会给一个时间,权值比 询问值小的边就可以走 从u到v 和从v到u算不同的两次 输出有多少种不同的走法(大概是这个意思吧)先把边的权值 从小到大排 ...
- hdu 4813(2013长春现场赛A题)
把一个字符串分成N个字符串 每个字符串长度为m Sample Input12 5 // n mklmbbileay Sample Outputklmbbileay # include <iost ...
- HDU 5531 Rebuild
2015 ACM/ICPC 长春现场赛 E题 三分. 如果节点个数是奇数,那么直接列方程可以求解,因为,如果第一个圆半径变大,必然导致最后一个圆的半径变大, 所以,节点是奇数的时候,要么无解,要么只有 ...
- HDU 4816 Bathysphere (2013长春现场赛D题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4816 2013长春区域赛的D题. 很简单的几何题,就是给了一条折线. 然后一个矩形窗去截取一部分,求最 ...
- HDU 4764 Stone (2013长春网络赛,水博弈)
Stone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 2015长春 HDU 5531 Rebuild
题意:n个顶点组成的多边形能否形成正多边形? #include <cstdio> #include <cstring> #include <cmath> #incl ...
随机推荐
- 带你走进EJB--那些跟EJB容器相关的那些Java概念
最近在对EJB的相关内容进行总结,在总结的过程中发现对容器的概念并不是很理解,因为EJB本身就是一个容器,但是容器到底是用来做什么的?它跟我们之前所了解的组件,框架,包,类等都有什么关系?接下来主要是 ...
- 大流量IIS负载均衡NLB解决方案
说白了就是 用多台WEB服务器 同时处理大量的http请求! 机器越多力量越大呵呵!!! 在现行的许多网络应用中,有时一台服务器往往不能满足客户端的要求,此时只能通过增加服务器来解决问题. 那么 ...
- UVa 10883 (组合数 对数) Supermean
在纸上演算一下就能看出答案是:sum{ C(n-1, i) * a[i] / 2^(n-1) | 0 ≤ i ≤ n-1 } 组合数可以通过递推计算:C(n, k) = C(n, k-1) * (n- ...
- UVa 557 (概率 递推) Burger
题意: 有两种汉堡给2n个孩子吃,每个孩子在吃之前要抛硬币决定吃哪一种汉堡.如果只剩一种汉堡,就不用抛硬币了. 求最后两个孩子吃到同一种汉堡的概率. 分析: 可以从反面思考,求最后两个孩子吃到不同汉堡 ...
- Entity Framework查询,EF执行SQl
一.简介 EF 支持开放底层的 ADO.NET 框架,DbContext有三种常用方法 DbSet.SqlQuery //查询并返回Entities DbContext.Database.SqlQue ...
- 完整cocos2d-x编译Andriod应用过程
作者:何卫 转载请注明,原文链接:http://www.cnblogs.com/hewei2012/p/3366969.html 其他平台移植:http://cocos2d.cocoachina.co ...
- HDU 5296 Annoying problem (LCA,变形)
题意: 给一棵n个节点的树,再给q个操作,初始集合S为空,每个操作要在一个集合S中删除或增加某些点,输出每次操作后:要使得集合中任意两点互可达所耗最小需要多少权值.(记住只能利用原来给的树边.给的树边 ...
- 【打表】HDOJ-2089-不要62
[题目链接:HDOJ-2089] 多组测试数据,所以可以先算出符合条件的所有数保存数组中,输入时则直接遍历数组. #include<iostream> #include<cstrin ...
- 五分钟solr4.5教程(搭建、运行)
环境要求 jdk1.6及以上版本 solr发布版本 下载地址 http://lucene.apache.org/solr/mirrors-solr-latest-redir.html? 启动solr ...
- j2ee的13个标准
1:JDBC(Java Database Connectivity)JDBC API为访问不同数据库提供了统一的路径,向ODBC一样,JDBC开发者屏蔽了一些细节问题,另外,JDBC对数据库的访问也具 ...