【Codeforces Beta Round 2C】【计算几何 转化 模拟退火】Commentator problem 求一个点,使得该点到三个圆的视角范围尽可能接近
2015-12-01 16:34
686 查看
C. Commentator problem
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard output
The Olympic Games in Bercouver are in full swing now. Here everyone has their own objectives: sportsmen compete for medals, and sport commentators compete for more convenient positions
to give a running commentary. Today the main sport events take place at three round stadiums, and the commentator's objective is to choose the best point of observation, that is to say the point from where all the three stadiums can be observed. As all the
sport competitions are of the same importance, the stadiums should be observed at the same angle. If the number of points meeting the conditions is more than one, the point with the maximum angle of observation is prefered.
Would you, please, help the famous Berland commentator G. Berniev to find the best point of observation. It should be noted, that the stadiums do not hide each other, the commentator
can easily see one stadium through the other.
Input
The input data consists of three lines, each of them describes the position of one stadium. The lines have the format x, y, r,
where (x, y) are the coordinates of the stadium's center ( - 103 ≤ x, y ≤ 103),
and r (1 ≤ r ≤ 103)
is its radius. All the numbers in the input data are integer, stadiums do not have common points, and their centers are not on the same line.
Output
Print the coordinates of the required point with five digits after the decimal point. If there is no answer meeting the conditions, the program shouldn't print anything. The output
data should be left blank.
Sample test(s)
input
output
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
const int N=0,M=0,Z=1e9+7,ms63=1061109567;
struct Circle
{
double x,y,r;
}c[3];
double ang[3];
const int dy[4]={-1,0,0,1};
const int dx[4]={0,-1,1,0};
double K(double x)
{
return x*x;
}
double Dis(double x,double y,double xx,double yy)
{
return sqrt(K(x-xx)+K(y-yy));
}
double Val(double x,double y)
{
for(int i=0;i<3;++i)ang[i]=Dis(x,y,c[i].x,c[i].y)/c[i].r;
double val=0;
for(int i=0;i<3;++i)val+=K(ang[i]-ang[(i+1)%3]);
return val;
}
int main()
{
double x=0,y=0;
for(int i=0;i<3;++i)
{
scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);
x+=c[i].x/3;y+=c[i].y/3;
}
double err=Val(x,y);
double step=1;
for(int tim=1;tim<=1e5;++tim)
{
bool flag=0;
double X,Y;
for(int i=0;i<4;++i)
{
double xx=x+dx[i]*step,yy=y+dy[i]*step;
double val=Val(xx,yy);
if(val<err)
{
err=val;
flag=1;
X=xx;Y=yy;
}
}
if(flag){x=X;y=Y;}
else step/=2;
}
if(err<1e-6)printf("%.5f %.5f\n",x,y);
return 0;
}
/*
【trick&&吐槽】
啦啦啦!
【题意】
给你三个圆,让你找到一个点,使得从这个点出发,看三个圆的视角范围的角度都一样。
如果有多个满足要求的点,我们希望找到一个点,使得这个视角范围的角度尽可能大。
(如果无解就不输出)
【类型】
计算几何公式求解or模拟退火
【分析】
这题可以直接解方程,用计算几何的方法做。
然而最好的,最值得学习有推广价值的算法还是——模拟退火。
什么是模拟退火呢?以后我们可以再慢慢具体学习。(才不是因为我现在不会啦~ T_T )
按照这道题的学习,大体上是这样做——
bas,设计估价函数
1,初始找一个近似最优解,
2,然后在最优解的四周寻求更优解。这里要保证步长不要太小,否则可能陷入局部最优解。
3,重复步骤2,适当调整步长,继续寻找最优解,直到达到精度要求。
在这道题上——
估价函数要先求出(距离/半径),这个数值和视角大小有相应的一一对应关系。
然后求出三个圆pair的(距离/半径)的差值的平方和,作为估价函数。
这个值越小,越接近零,显然对于三个圆的视角越接近。
1是重心
2初始为1,找得到更优就继续走。找不到更优就步长缩半
3直到一定的次数或一定的精度
然后这道题就做完啦!做完啦!做完啦!
以后再来加深学习模拟退火哦~~!
====================================================================
当然这题有解方程做法啦。因为满足要求的点数其实一筛就没几个了哦~以后再补!
【时间复杂度&&优化】
O(模拟退火次数)
*/
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard output
The Olympic Games in Bercouver are in full swing now. Here everyone has their own objectives: sportsmen compete for medals, and sport commentators compete for more convenient positions
to give a running commentary. Today the main sport events take place at three round stadiums, and the commentator's objective is to choose the best point of observation, that is to say the point from where all the three stadiums can be observed. As all the
sport competitions are of the same importance, the stadiums should be observed at the same angle. If the number of points meeting the conditions is more than one, the point with the maximum angle of observation is prefered.
Would you, please, help the famous Berland commentator G. Berniev to find the best point of observation. It should be noted, that the stadiums do not hide each other, the commentator
can easily see one stadium through the other.
Input
The input data consists of three lines, each of them describes the position of one stadium. The lines have the format x, y, r,
where (x, y) are the coordinates of the stadium's center ( - 103 ≤ x, y ≤ 103),
and r (1 ≤ r ≤ 103)
is its radius. All the numbers in the input data are integer, stadiums do not have common points, and their centers are not on the same line.
Output
Print the coordinates of the required point with five digits after the decimal point. If there is no answer meeting the conditions, the program shouldn't print anything. The output
data should be left blank.
Sample test(s)
input
0 0 10 60 0 10 30 30 10
output
30.00000 0.00000
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
const int N=0,M=0,Z=1e9+7,ms63=1061109567;
struct Circle
{
double x,y,r;
}c[3];
double ang[3];
const int dy[4]={-1,0,0,1};
const int dx[4]={0,-1,1,0};
double K(double x)
{
return x*x;
}
double Dis(double x,double y,double xx,double yy)
{
return sqrt(K(x-xx)+K(y-yy));
}
double Val(double x,double y)
{
for(int i=0;i<3;++i)ang[i]=Dis(x,y,c[i].x,c[i].y)/c[i].r;
double val=0;
for(int i=0;i<3;++i)val+=K(ang[i]-ang[(i+1)%3]);
return val;
}
int main()
{
double x=0,y=0;
for(int i=0;i<3;++i)
{
scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);
x+=c[i].x/3;y+=c[i].y/3;
}
double err=Val(x,y);
double step=1;
for(int tim=1;tim<=1e5;++tim)
{
bool flag=0;
double X,Y;
for(int i=0;i<4;++i)
{
double xx=x+dx[i]*step,yy=y+dy[i]*step;
double val=Val(xx,yy);
if(val<err)
{
err=val;
flag=1;
X=xx;Y=yy;
}
}
if(flag){x=X;y=Y;}
else step/=2;
}
if(err<1e-6)printf("%.5f %.5f\n",x,y);
return 0;
}
/*
【trick&&吐槽】
啦啦啦!
【题意】
给你三个圆,让你找到一个点,使得从这个点出发,看三个圆的视角范围的角度都一样。
如果有多个满足要求的点,我们希望找到一个点,使得这个视角范围的角度尽可能大。
(如果无解就不输出)
【类型】
计算几何公式求解or模拟退火
【分析】
这题可以直接解方程,用计算几何的方法做。
然而最好的,最值得学习有推广价值的算法还是——模拟退火。
什么是模拟退火呢?以后我们可以再慢慢具体学习。(才不是因为我现在不会啦~ T_T )
按照这道题的学习,大体上是这样做——
bas,设计估价函数
1,初始找一个近似最优解,
2,然后在最优解的四周寻求更优解。这里要保证步长不要太小,否则可能陷入局部最优解。
3,重复步骤2,适当调整步长,继续寻找最优解,直到达到精度要求。
在这道题上——
估价函数要先求出(距离/半径),这个数值和视角大小有相应的一一对应关系。
然后求出三个圆pair的(距离/半径)的差值的平方和,作为估价函数。
这个值越小,越接近零,显然对于三个圆的视角越接近。
1是重心
2初始为1,找得到更优就继续走。找不到更优就步长缩半
3直到一定的次数或一定的精度
然后这道题就做完啦!做完啦!做完啦!
以后再来加深学习模拟退火哦~~!
====================================================================
当然这题有解方程做法啦。因为满足要求的点数其实一筛就没几个了哦~以后再补!
【时间复杂度&&优化】
O(模拟退火次数)
*/
相关文章推荐
- 【Educational Codeforces Round 1A】【水题】Tricky Sum 1~n之和减去2的幂
- 【Educational Codeforces Round 1B】【字符串平移 水题】Queries on a String 字符串平移水题
- 【Educational Codeforces Round 1C】【计算几何-极角排序 atan2 long double】Nearest vectors 平面图上原点引出角度最小的两个
- 【Educational Codeforces Round 1D】【DFS 联通块打标记法】Igor In the Museum 联通块内墙的面数
- 【Educational Codeforces Round 1E】【动态规划-多维DP】Chocolate Bar 矩形巧克力掰开吃的最小成本
- 【Codeforces Round 299 (Div 2)D】【KMP 本质是最前与最后匹配】Tavas and Malekas 长度为n的匹配串被模板串多位点覆盖的匹配串个数
- 【Codeforces Round 333 (Div 2)A 】【水题 简单进制模拟】Two Bases 不同进制数比大小
- 【Codeforces Round 333 (Div 2)B】【贪心 多指针】Approximating a Constant Range 给定数组 相邻元素波动为1 求差值不超1的最长序连续子序列
- 【Codeforces Round 333 (Div 2)C】【最短路】The Two Routes 完全图两种双向边的最小最大距离
- 【Codeforces Round 333 (Div 2)D】【线段树 or ST-RMQ 初始化78msAC】Lipshitz Sequence 若干区间询问所有子区间的答案和
- 【Codeforces Round 333 (Div 2)E】【期望DP概率做法 树状数组转前缀和】Kleofáš and the n-thlon n场比赛m个人获得总名次的期望
- 【Codeforces Testing Round 12A】【讨论 边界元素映射】Divisibility 区间范围内k倍数的数的个数
- 【Codeforces Testing Round 12B】【贪心】Restaurant 选取数量最多的不覆盖区间数
- 【Codeforces Testing Round 12C】【DP 树状数组优化】Subsequences n个不同数,长度为m的LIS数
- 【Educational Codeforces Round 2B】【map or 二分查找】Queries about less or equal elements b[]中的每个数比a[]中多少数大
- 【Educational Codeforces Round 2C】【贪心】最少修改数下得到字典序尽可能小回文串
- 【Educational Codeforces Round 2D】【计算几何 圆面积交 模板】Area of Two Circles' Intersection
- 【Educational Codeforces Round 2E】【STL-map 启发式合并 or 线段树动态开节点 】Lomsat gelral 一棵树每点一个颜色问每个节点子树的颜色众数之和
- 【Codeforces Beta Round 2A】【模拟 map 有map的java实现哦】Winner 第一个达到最终最高分的人名
- 【Codeforces Round 169 (Div 2) E】【数据结构区间维护】Little Girl and Problem on Trees 大菊花树的距离性修改查询