TopCoder SRM 559 Div 1 - Problem 900 CircusTents

题目简述:

n个实心圆,两两没有交集,在第一个圆上找一个点,使得它到另外一个圆上某个点的最短距离的最小值尽量大,两个点之间的最短距离是指连接两个点且中途不进入任何一个实心圆内部的路径的长度的最小值。

二分答案:

很显然,这题跟二分答案有关。

思路:

我们先考虑,如果第一个圆上的点确定了下来,它到别的所有的圆的距离的最小值。

The First Case:

The Second Case:

图中蓝色线是最短的路径。

当然还有第三种情况,就是路径过程中与别的圆相交了。不过这样肯定不是所有的路中最短的,所以可以忽略这种情况。

那么接下来考虑二分答案。

对于当前二分到的mid,

检查最终答案是否>=mid。

即是否存在最短路径都>=mid的点。

那么一个很简单的思路就出来了,对于每个圆,起点到它的最短路>=mid,可以确定起点一定不在圆上的某条弧上。

同样分两种情况,求出所有的起点位置限制。最后对这些位置限制(弧)排个序,判断合不合法即可。

题外话:

为了图方便,打算用余弦定理求位置限制,结果把公式背错了,对着样例调试了好久??

代码:

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <string>
  4 #include <vector>
  5 #include <cstring>
  6 #include <iostream>
  7 #include <algorithm>
  8 using namespace std;
  9 #define _CLASSNAME_ CircusTents
 10 #define _METHODNAME_ findMaximumDistance
 11 #define _RC_ double
 12 #define _METHODPARMS_ vector <int> x, vector <int> y, vector <int> r
 13 #define ref(i,x,y)for(int i=x;i<=y;++i)
 14 #define def(i,x,y)for(int i=x;i>=y;--i)
 15 typedef long double LD;
 16 const int N = 51;
 17 const LD pi = acos(-1);
 18 int n;
 19 struct xint { int x, y, r; }s[N];
 20 struct yint { LD op, ed; }S[N];
 21 bool cmp(yint a, yint b) { return a.op < b.op; }
 22 bool check(LD ss) {
 23     ref(i, 2, n) {
 24         LD _min = sqrt(s[i].x*s[i].x + s[i].y*s[i].y) - s[1].r;
 25         LD _max = sqrt(s[i].x*s[i].x + s[i].y*s[i].y - s[1].r*s[1].r);
 26         LD _dis = s[i].r + ss;
 27         if (_dis < _min) {
 28             S[i].op = 0, S[i].ed = 0; continue;
 29         }
 30         LD b = atan2(s[i].y, s[i].x); if (b < 0)b = 2 * pi + b;
 31         if (_dis > _max) {
 32             LD a = (_dis - _max) / s[1].r + acos(s[1].r / sqrt(s[i].x*s[i].x + s[i].y*s[i].y));
 33             if (a > pi)S[i].op = 0, S[i].ed = 2 * pi;
 34             else S[i].op = b - a, S[i].ed = b + a;
 35         }
 36         else {
 37             LD dis2 = s[i].x*s[i].x + s[i].y*s[i].y;
 38             //s[1].r*s[1].r + dis2 - 2 * s[1].r*sqrt(dis2)* cos(alpha) = _dis*_dis;
 39             LD a = acos((s[1].r*s[1].r + dis2 - _dis*_dis) / 2 / s[1].r / sqrt(dis2));
 40             S[i].op = b - a, S[i].ed = b + a;
 41         }
 42         if (S[i].ed > 2 * pi)S[i].op -= 2 * pi, S[i].ed -= 2 * pi;
 43     }
 44     LD LL = 0, RR = 2 * pi;
 45     sort(S + 2, S + n + 1, cmp);
 46     ref(i, 2, n) {
 47         if (S[i].op < 0)LL = max(LL, S[i].ed), RR = min(RR, S[i].op + 2 * pi);
 48         else {
 49             if (LL < S[i].op)return 1;
 50             if (S[i].ed > LL)LL = S[i].ed;
 51         }
 52         if (LL >= RR)return 0;
 53     }
 54     return 1;
 55 }
 56 LD work() {
 57     LD L = -1e6, R = 1e6;
 58     ref(times, 1, 50) {
 59         LD mid = (L + R) / 2;
 60         if (check(mid))L = mid; else R = mid;
 61     }
 62     return L;
 63 }
 64 class _CLASSNAME_ {
 65 public:
 66     _RC_ _METHODNAME_(_METHODPARMS_)
 67     {
 68         n = x.size();
 69         ref(i, 1, n)s[i].x = x[i - 1], s[i].y = y[i - 1], s[i].r = r[i - 1];
 70         ref(i, 2, n)s[i].x -= s[1].x, s[i].y -= s[1].y; s[1].x = s[1].y = 0;
 71         return _RC_(work());
 72     }
 73
 74     // BEGIN CUT HERE
 75 public:
 76     void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }
 77 private:
 78     template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << ‘\"‘ << *iter << "\","; os << " }"; return os.str(); }
 79     void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << ‘\"‘ << endl; cerr << "\tReceived: \"" << Received << ‘\"‘ << endl; } }
 80     void test_case_0() { int Arr0[] = { 0,3 }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = { 0,0 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = { 1,1 }; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 3.7390603609952078; verify_case(0, Arg3, findMaximumDistance(Arg0, Arg1, Arg2)); }
 81     void test_case_1() { int Arr0[] = { 0,3,-3,3,-3 }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = { 0,3,3,-3,-3 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = { 1,1,1,1,1 }; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 2.6055512754639887; verify_case(1, Arg3, findMaximumDistance(Arg0, Arg1, Arg2)); }
 82     void test_case_2() { int Arr0[] = { 3,7,7,7,3 }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = { 4,6,1,-3,0 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = { 2,2,2,1,1 }; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 4.3264459099620725; verify_case(2, Arg3, findMaximumDistance(Arg0, Arg1, Arg2)); }
 83     void test_case_3() { int Arr0[] = { 10,-1 }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = { 0,0 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = { 8,2 }; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 24.63092458664212; verify_case(3, Arg3, findMaximumDistance(Arg0, Arg1, Arg2)); }
 84     void test_case_4() { int Arr0[] = { 0,4,-4 }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = { 0,4,-4 }; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = { 1,1,1 }; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 4.745474963675133; verify_case(4, Arg3, findMaximumDistance(Arg0, Arg1, Arg2)); }
 85     // END CUT HERE
 86
 87 };
 88
 89 // BEGIN CUT HERE
 90 int main()
 91 {
 92     /*
 93     {3, 7, 7, 7, 3}
 94     {4, 6, 1, -3, 0}
 95     {2, 2, 2, 1, 1}
 96     */
 97     CircusTents ___test;
 98     ___test.run_test(-1);
 99     getchar();
100     return 0;
101 }
102 // END CUT HERE
时间: 2024-10-07 09:30:09

TopCoder SRM 559 Div 1 - Problem 900 CircusTents的相关文章

TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization &amp; Codeforces 839 E

传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相加,含有n个不同变量的式子的最大值. 另外限制了每一个变量的最大最小值R[i]和L[i]和所有变量之和的最大值Max. n<=13 题外话: 刚开始做这道题的时候,感觉意外眼熟? codeforces 839 E(此题的退化版):http://codeforces.com/contest/839/pro

TopCoder SRM 558 Div 1 - Problem 1000 SurroundingGame

题目简述  一个人在一个n * m棋盘上玩游戏,想要占领一个格子有两个方法: 在这个格子放一个棋子.  这个格子周围(四联通)的格子中**都有棋子**. 在(i, j)中放棋子需要花费cost[i][j],占领(i, j)能获得benefit[i][j].求一种放置棋子的方法,使得总收益(收益 - 花费)最大. 2<=n,m<=20 分析 一眼看上去, 状压? 我是不是dp学傻了..根本想不出 网络流? 嗯,此题是一道非常套路的网络流练习题. 如果想不到对棋盘进行黑白染色,就GG了. 所以套路

TopCoder SRM 561 Div 1 - Problem 1000 Orienteering

传送门:https://284914869.github.io/AEoj/561.html 题目简述: 题外话: 刚开始看题没看到|C|<=300.以为|C|^2能做,码了好久,但始终解决不了一棵树中多条直径去重的问题.后来才发现|C|<=300,暴力就可以了. 不知道有哪位大佬会|C|^2的做法?? 思路: 很显然,若length为树中经过所有S中的点的最短路径长度, 若size为虚树中所有边的长度和, 若dis为虚树中的最远点对的距离(即直径长度) 那么length=size*2-dis.

TopCoder SRM 628 DIV 2

250-point problem Problem Statement    Janusz is learning how to play chess. He is using the standard chessboard with 8 rows and 8 columns. Both the rows and the columns are numbered 0 through 7. Thus, we can describe each cell using its two coordina

TopCoder SRM 634 Div.2[ABC]

TopCoder SRM 634 Div.2[ABC] ACM 题目地址: TopCoder SRM 634 赛后做的,感觉现场肯定做不出来Orz,简直不能多说. Level One-MountainRanges[水题] 题意: 问序列中有几个完全大于旁边的峰. 分析: 傻逼题,不多说. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: one.cpp * Create Date: 2014-09-26 21:01:23 * Desc

TopCoder SRM 596 DIV 1 250

body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } Problem Statement      You have an array with N elements. Initially, each element is 0. You can perform the following operations: Increment operation:

[topcoder]SRM 633 DIV 2

第一题,http://community.topcoder.com/stat?c=problem_statement&pm=13462&rd=16076 模拟就可以了. #include <vector> #include <algorithm> using namespace std; class Target { public: vector <string> draw(int n) { vector<string> result(n,

[topcoder]SRM 646 DIV 2

第一题:K等于1或者2,非常简单.略.K更多的情况,http://www.cnblogs.com/lautsie/p/4242975.html,值得思考. 第二题:http://www.cnblogs.com/lautsie/p/4245242.html BFS和DFS都可以,注意的是,写的时候,可以往que里几个东西一起扔,就不用建立对象了.也可以直接用二维矩阵记录blocked和visited. 剪枝什么的,最基本的是发现其实在步数限制的情况下,棋盘就是有界的了. 第三题:http://ap

Topcoder SRM 687 (Div 2) 250.Quorum

Problem Statement   In one organization they have n different committees. The organization has a very large number of employees. Each employee is a member of each committee. Each committee has a quorum: the smallest number of members that have to be