HDU 4791 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

Problem Description

Archaeologists find ruins of Ancient ACM Civilization, and they want to rebuild it.

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.

Input

The first line contains an integer t indicating the total number of test cases. The following lines describe a test case.

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.

Output

If such answer doesn‘t exist, then print on a single line "IMPOSSIBLE" (without the quotes). Otherwise, in the first line print the minimum sum of base area, and then print n lines, the i-th of them should contain a number ri, rounded to 2 digits after the decimal point.

If there are several possible ways to produce the minimum sum of base area, you may output any of them.

Sample Input

3
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

Sample Output

988.82
3.75
7.25
12.75
9.25
157.08
6.00
1.00
2.00
3.00
0.00
IMPOSSIBLE

Source

2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)

【题意】:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define eps 1e-8
  7 #define PI acos(-1.0)
  8 #define LL long long
  9 #define maxn 100100
 10 #define IN freopen("in.txt","r",stdin);
 11 using namespace std;
 12
 13
 14 struct Point {
 15     double x,y;
 16 };
 17
 18 int sign(double x) {
 19     if(fabs(x)<eps) return 0;
 20     return x<0? -1:1;
 21 }
 22
 23 double Distance(Point p1,Point p2) {
 24     return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
 25 }
 26
 27
 28 int n;
 29 Point p[maxn];
 30 double d[maxn];
 31
 32 int check(double r)
 33 {
 34     if(sign(r) < 0) return 0;
 35
 36     for(int i=2 ;i<=n; i++) {
 37         r = d[i]-r;
 38         if(sign(r) < 0) return 0;
 39     }
 40     return 1;
 41 }
 42
 43
 44 /*三分法求面积最小时的r*/
 45 double a,b,c;
 46 double cal(double x) {
 47     return a*x*x + b*x + c;
 48 }
 49
 50 double solve(double low, double high)
 51 {
 52     while(high-low > eps){
 53         double mid = (high+low)/2.0;
 54         double midmid = (mid+high)/2.0;
 55         if(sign(cal(midmid)-cal(mid)) > 0) high = midmid;
 56         else low = mid;
 57     }
 58
 59     return low;
 60 }
 61
 62
 63 int main(int argc, char const *argv[])
 64 {
 65     //IN;
 66
 67     int t;scanf("%d",&t);
 68     while(t--)
 69     {
 70         double r = 0;
 71         memset(p, 0, sizeof(p));
 72         memset(d, 0, sizeof(d));
 73         int flag = 1;
 74
 75         scanf("%d", &n);
 76         for(int i=1 ;i<=n; i++)
 77             scanf("%lf %lf", &p[i].x, &p[i].y);
 78         d[1]=Distance(p[1], p[n]);
 79         for(int i=2; i<=n; i++)
 80             d[i] = Distance(p[i], p[i-1]);
 81
 82         if(n%2 != 0){
 83             r = d[1];
 84             for(int i=2; i<=n; i++){
 85                 if(i%2 == 0) r += d[i];
 86                 else r -= d[i];
 87             }
 88             r /= 2.0;
 89             flag = check(r);
 90         }
 91
 92         else{
 93             double tmp = 0;
 94             for(int i=1; i<=n; i++){
 95                 if(i%2 != 0) tmp += d[i];
 96                 else tmp -= d[i];
 97             }
 98             if(sign(tmp) != 0) {flag=0; goto end;}
 99
100             /*半径平方和的二次表达式*/
101             a=1.0; b=0; c=0;
102             tmp = 0;
103             for(int i=2; i<=n; i++){
104                 a += 1.0;
105                 tmp = d[i]-tmp;
106                 c += tmp*tmp;
107                 if(i%2 == 0) b -= 2.0*tmp;
108                 else b += 2.0*tmp;
109             }
110
111             /*
112                 错误地以为最低点为唯一取值点,若最低点不符合则无解.
113                 r=(-b)/(2.0*a);
114                 if(sign(r)<0) r=0;
115                 flag = check(r);
116             */
117
118             /*检查每条边计算三分时r的可行范围*/
119             double low=0, high = d[1];
120             tmp = 0;
121             for(int i=2; i<=n; i++){
122                 if(i%2 == 0){
123                     tmp += d[i];
124                     high = min(high, tmp);
125                 }
126                 else{
127                     tmp -= d[i];
128                     low = max(low, tmp);
129                 }
130             }
131
132             if(low > high) flag = 0;
133             else{
134                 r = solve(low, high);
135                 flag = check(r);
136             }
137         }
138
139         end:
140         if(!flag) printf("IMPOSSIBLE\n");
141         else{
142             double R[maxn];
143             R[1]=r;
144             double temp = 0;
145             for(int i=2; i<=n; i++){
146                 temp = d[i]-R[i-1];
147                 R[i] = temp;
148             }
149             double ans = 0;
150             for(int i=1; i<=n; i++){
151                 //ans += R[i]*R[i]*PI;精度问题
152                 ans += R[i]*R[i];
153             }
154
155             printf("%.2lf\n", ans*PI);
156             for(int i=1; i<=n; i++){
157                 printf("%.2lf\n", R[i]);
158             }
159         }
160
161     }
162
163     return 0;
164 }
时间: 2024-11-13 08:46:38

HDU 4791 Rebuild (2015长春现场赛,计算几何+三分)的相关文章

hdu 5441 Travel (2015长春网赛)

http://acm.hdu.edu.cn/showproblem.php?pid=5441 题目大意是给一个n个城市(点)m条路线(边)的双向的路线图,每条路线有时间值(带权图),然后q个询问,每个询问一个时间值 求不大于这个时间的可以连通的城市有多少种连法 比如样例中第一个询问6000,不大于6000时间值的连通城市有3,5.所以有3-->5,5-->3两种 第二个询问10000,符合条件的连通的城市有2,3,5,所以有2-->3,3-->2,2-->5,5-->2

2015长春现场赛

1.Alisha’s Party(hdu 5437) 优先队列模拟,共k个人,每个人有一个价值,m次进入,每次价值最大的进去,价值相同id小的先进去,a b前a个没进去的人进去b个,不够b个,都进去,m次操作后,剩下的都进去,最后输出查询的第i个进去的人的名字 需要注意的是,m是乱序给的,需要按照a进行排序 #include<bits/stdc++.h> using namespace std; const int maxn=150005; char name[maxn][205]; type

hdu 5441 (2015长春网络赛E题 带权并查集 )

n个结点,m条边,权值是 从u到v所花的时间 ,每次询问会给一个时间,权值比 询问值小的边就可以走 从u到v 和从v到u算不同的两次 输出有多少种不同的走法(大概是这个意思吧)先把边的权值 从小到大排序 询问值也按从小到大排序num记录集合里元素的个数每合并两个集合 ans增加 2*num[u]*num[v] Sample Input15 5 3 //n w q2 3 63341 5 157243 5 57054 3 123821 3 2172660001000013000 Sample Out

hdu 4813(2013长春现场赛A题)

把一个字符串分成N个字符串 每个字符串长度为m Sample Input12 5 // n mklmbbileay Sample Outputklmbbileay 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <string> 6 # include <cmath> 7 # in

HDU 4815 2013长春现场赛C题

C - Little Tiger vs. Deep Monkey Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4815 Description A crowd of little animals is visiting a mysterious laboratory ? The Deep Lab of SYSU. "Are y

hdu 4465 Candy 2012 成都现场赛

1 /** 2 对于大数的很好的应用,,缩小放大,,保持精度 3 **/ 4 #include <iostream> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstdio> 8 using namespace std; 9 10 int main() 11 { 12 double n,p; 13 int cnt =1; 14 while(cin>>n>>p){ 15

2015长春网络赛总结

早上七点多就(冻)醒来了,训练了一个暑假,acm生涯的第一场网络赛,很激动. 九点开打,我拔不出网线,用的机房电脑,装的cb有问题,不能编译,只好用dev.男神电脑插上网线没有网,习惯了linux可能不习惯吧.这提醒我们以后一定要早点去把环境调好. 第三分钟,G题有人A了.我跟560开始看题,男神还在弄电脑.题意是给你n个数(n<1000),然后q(q<1000)次询问,要求你输出[l,r]区间的最大值.数据很小,我说暴力,然后560说线段树,然后模板13分钟1Y.然后560开始搞J,一个貌似

hdu 5538 House Building(长春现场赛——水题)

题目链接:acm.hdu.edu.cn/showproblem.php?pid=5538 House Building Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 621    Accepted Submission(s): 398 Problem Description Have you ever played the vid

Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)

题目链接: Hdu 5439 Aggregated Counting 题目描述: 刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最后问a[i]==n(i最大)时候,i最后一次出现的下标是多少? 解题思路: 问题可以转化为求a[i] == n (i最大),数列前i项的和为多少. index: 1 2 3 4 5 6 7 8 9 10 a:        1 2 2 3 3 4 4 4 5 5 可以观察出:ans[1] = 1,