[HDU]5531 Rebuild (三分法求下凸函数,维护最小圆面积)
来源:互联网 发布:农家乐商机数据 编辑:程序博客网 时间:2024/06/05 09:07
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5531
题目大意:给定一个凸N边形N个顶点坐标(N>=3),在N边形每个顶点上构造一个圆要求相邻两顶点的圆相切,求能构造出的最小总圆面积
数据范围: 3 <= N <= 10000, 3 <= xi , yi <= 10000
题目解答:三分法求下凸函数(复杂度O(N*log3(N)))
假设第一个点构造的圆半径为r,则其他点构造出的圆的半径可以依次表示出来,最后的答案是关于r的一个二次函数。
对于N边形分奇偶讨论:
- N为奇数:此时关于r的二次函数没有r的一次项,则最终面积结果可以直接求解
- N为偶数:此时关于r的二次函数有r的一次项,是一个下凸函数,想到三分求解
注意:三分的时候边界条件处理不好可能会导致WA,注意对最后二分出的结果取(l+r)/ 2作为答案
#include <set>#include <map>#include <stack>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const double pi = acos(-1.0);const double eps = 1e-9;const int maxn = 100010;int n;double dis[maxn], ri[maxn];///dis存边长,ri存半径struct Edge{ double x, y;}e[maxn];int Dcmp(double x){ if(fabs(x) < eps) return 0; if(x > 0) return 1; return -1;}double Dis(int i, int j){ return sqrt((e[i].x-e[j].x)*(e[i].x-e[j].x) + (e[i].y-e[j].y)*(e[i].y-e[j].y));}double ans;int Check(double r){ double tmp = -r; for(int i = 0; i < n; ++i) { tmp = dis[i] - tmp; ri[i] = tmp; if(Dcmp(tmp) < 0) return 0; } ans = 0; for(int i = 0; i < n; ++i) ans += ri[i] * ri[i]; return 1;}int main(){ int t, ca = 1; scanf("%d", &t); while(t--) { scanf("%d", &n); dis[0] = 0; for(int i = 0; i < n; ++i) { scanf("%lf %lf", &e[i].x, &e[i].y); if(i) dis[i] = Dis(i,i-1); if(i == n-1) dis[n] = Dis(i,0); } double mn = 0, mx = dis[1]; double sum = 0; for(int i = 1; i <= n; ++i) { sum = dis[i] - sum; if(i & 1) mx = min(mx,sum); else mn = max(mn,-sum); } if(Dcmp(mx - mn) < 0) { printf("IMPOSSIBLE\n"); continue; } if(n & 1) { double r = sum / 2; if(!Check(r) || Dcmp(r) <= 0 ) printf("IMPOSSIBLE\n"); else { printf("%.2f\n", ans*pi); for(int i = 0; i < n; ++i) printf("%.2f\n", ri[i]); } } else { if(Dcmp(sum) != 0) { printf("IMPOSSIBLE\n"); continue; } double l = mn, r = mx; double mid, mmid, s1, s2; while(l+eps < r) { mid = (l+r)/2; mmid = (mid+r)/2; Check(mid); s1 = ans; Check(mmid); s2 = ans; if(s1 <= s2) r = mmid; else l = mid; } if(Check((l+r)/2)) { printf("%.2f\n", ans*pi); for(int i = 0; i < n; ++i) printf("%.2f\n", ri[i]); } else printf("IMPOSSIBLE\n"); } } return 0;}
0 0
- [HDU]5531 Rebuild (三分法求下凸函数,维护最小圆面积)
- hdu 3007 最小圆覆盖(模版)
- hdu 3007(最小圆覆盖)
- hdu 5531 Rebuild(三分)
- hdu 5531 Rebuild(三分)
- zju 3421 Error Curves(凸函数最值,三分法)
- HDU 3007 最小圆覆盖
- hdu 2215(最小圆覆盖)
- HDU 3007 最小圆覆盖
- HDU 5531 Rebuild (三分) ★ ★
- hdu 5531 Rebuild 三分
- HDU 5531(Rebuild- 三分)
- HDU 5531 Rebuild(三分)
- HDU 5531 Rebuild 题解
- HDU 5531 Rebuild(几何)
- HDU 4766 模拟退火(最小圆覆盖) + 二分
- hdu 3932 Groundhog Build Home (最小圆覆盖)
- 三分法求解凸函数的最值!!!
- 剑指Offer 9题 斐波那契数列(Fibonacci) Java版
- 去除CSDN 博客页广告的历程
- JS中各种宽度距离小结
- [数据库连接池] Java数据库连接池--DBCP浅析.
- Chrome“无法添加来自此网站的应用”的解决办法
- [HDU]5531 Rebuild (三分法求下凸函数,维护最小圆面积)
- 两个辅助指针变量挖字符串(4种实现方式)
- C/C++野指针
- 1.mysql bin-log日志基本操作与数据库备份还原
- scipy求一些统计量的p值和分位数
- C Primer Plus学习 十六 函数概述
- android中data binding的使用
- viewpager过渡页
- SQL存储过程返回受影响的行数