Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) D. Volatile Kite
地址:http://codeforces.com/contest/801/problem/D
题目:
2 seconds
256 megabytes
standard input
standard output
You are given a convex polygon P with n distinct vertices p1, p2, ..., pn. Vertex pi has coordinates (xi, yi) in the 2D plane. These vertices are listed in clockwise order.
You can choose a real number D and move each vertex of the polygon a distance of at most D from their original positions.
Find the maximum value of D such that no matter how you move the vertices, the polygon does not intersect itself and stays convex.
The first line has one integer n (4 ≤ n ≤ 1 000) — the number of vertices.
The next n lines contain the coordinates of the vertices. Line i contains two integers xi and yi ( - 109 ≤ xi, yi ≤ 109) — the coordinates of the i-th vertex. These points are guaranteed to be given in clockwise order, and will form a strictly convex polygon (in particular, no three consecutive points lie on the same straight line).
Print one real number D, which is the maximum real number such that no matter how you move the vertices, the polygon stays convex.
Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.
Namely, let's assume that your answer is a and the answer of the jury is b. The checker program will consider your answer correct if
.
4
0 0
0 1
1 1
1 0
0.3535533906
6
5 0
10 0
12 -4
10 -8
5 -8
3 -4
1.0000000000
Here is a picture of the first sample

Here is an example of making the polygon non-convex.

This is not an optimal solution, since the maximum distance we moved one point is ≈ 0.4242640687, whereas we can make it non-convex by only moving each point a distance of at most ≈ 0.3535533906.
思路:这题看起来很复杂,但是看下样例一的图后会发现一个结论:
在相邻的三个点a,b,c中,能移动的最大距离d就是b到直线ac的距离的一半。
证明:当d大于一半时,凸包会被破坏。
当d小于一半时,凸包仍然存在(即可以继续移动)

所以贴个求点到直线的模板,然后扫一遍所有点,求出所有可移动距离的最大值中的最小值即可。
(完整代码模板我博客有
#include <bits/stdc++.h> using namespace std; #define MP make_pair
#define PB push_back
typedef long long LL;
typedef pair<int,int> PII;
const double eps=1e-;
const double pi=acos(-1.0);
const int K=1e6+;
const int mod=1e9+; //点
class Point
{
public:
double x, y; Point(){}
Point(double x, double y):x(x),y(y){} bool operator < (const Point &_se) const
{
return x<_se.x || (x==_se.x && y<_se.y);
}
/*******判断ta与tb的大小关系*******/
static int sgn(double ta,double tb)
{
if(fabs(ta-tb)<eps)return ;
if(ta<tb) return -;
return ;
}
static double xmult(const Point &po, const Point &ps, const Point &pe)
{
return (ps.x - po.x) * (pe.y - po.y) - (pe.x - po.x) * (ps.y - po.y);
}
friend Point operator + (const Point &_st,const Point &_se)
{
return Point(_st.x + _se.x, _st.y + _se.y);
}
friend Point operator - (const Point &_st,const Point &_se)
{
return Point(_st.x - _se.x, _st.y - _se.y);
}
//点位置相同(double类型)
bool operator == (const Point &_off) const
{
return Point::sgn(x, _off.x) == && Point::sgn(y, _off.y) == ;
}
//点位置不同(double类型)
bool operator != (const Point &_Off) const
{
return ((*this) == _Off) == false;
}
//两点间距离的平方
static double dis2(const Point &_st,const Point &_se)
{
return (_st.x - _se.x) * (_st.x - _se.x) + (_st.y - _se.y) * (_st.y - _se.y);
}
//两点间距离
static double dis(const Point &_st, const Point &_se)
{
return sqrt((_st.x - _se.x) * (_st.x - _se.x) + (_st.y - _se.y) * (_st.y - _se.y));
}
};
//两点表示的向量
class Line
{
public:
Point s, e;//两点表示,起点[s],终点[e]
double a, b, c;//一般式,ax+by+c=0 Line(){}
Line(const Point &s, const Point &e):s(s),e(e){}
Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){} //向量与点的叉乘,参数:点[_Off]
//[点相对向量位置判断]
double operator /(const Point &_Off) const
{
return (_Off.y - s.y) * (e.x - s.x) - (_Off.x - s.x) * (e.y - s.y);
}
//向量与向量的叉乘,参数:向量[_Off]
friend double operator /(const Line &_st,const Line &_se)
{
return (_st.e.x - _st.s.x) * (_se.e.y - _se.s.y) - (_st.e.y - _st.s.y) * (_se.e.x - _se.s.x);
}
friend double operator *(const Line &_st,const Line &_se)
{
return (_st.e.x - _st.s.x) * (_se.e.x - _se.s.x) - (_st.e.y - _st.s.y) * (_se.e.y - _se.s.y);
}
//从两点表示转换为一般表示
//a=y2-y1,b=x1-x2,c=x2*y1-x1*y2
bool pton()
{
a = e.y - s.y;
b = s.x - e.x;
c = e.x * s.y - e.y * s.x;
return true;
} //-----------点和直线(向量)-----------
//点在向量左边(右边的小于号改成大于号即可,在对应直线上则加上=号)
//参数:点[_Off],向量[_Ori]
friend bool operator<(const Point &_Off, const Line &_Ori)
{
return (_Ori.e.y - _Ori.s.y) * (_Off.x - _Ori.s.x)
< (_Off.y - _Ori.s.y) * (_Ori.e.x - _Ori.s.x);
} //点在直线上,参数:点[_Off]
bool lhas(const Point &_Off) const
{
return Point::sgn((*this) / _Off, ) == ;
}
//点在线段上,参数:点[_Off]
bool shas(const Point &_Off) const
{
return lhas(_Off)
&& Point::sgn(_Off.x - min(s.x, e.x), ) > && Point::sgn(_Off.x - max(s.x, e.x), ) <
&& Point::sgn(_Off.y - min(s.y, e.y), ) > && Point::sgn(_Off.y - max(s.y, e.y), ) < ;
} //点到直线/线段的距离
//参数: 点[_Off], 是否是线段[isSegment](默认为直线)
double dis(const Point &_Off, bool isSegment = false)
{
///化为一般式
pton(); //到直线垂足的距离
double td = (a * _Off.x + b * _Off.y + c) / sqrt(a * a + b * b); //如果是线段判断垂足
if(isSegment)
{
double xp = (b * b * _Off.x - a * b * _Off.y - a * c) / ( a * a + b * b);
double yp = (-a * b * _Off.x + a * a * _Off.y - b * c) / (a * a + b * b);
double xb = max(s.x, e.x);
double yb = max(s.y, e.y);
double xs = s.x + e.x - xb;
double ys = s.y + e.y - yb;
if(xp > xb + eps || xp < xs - eps || yp > yb + eps || yp < ys - eps)
td = min(Point::dis(_Off,s), Point::dis(_Off,e));
} return fabs(td);
}
}; int n;
Point pt[K];
Line ta;
double ans=1e10;
int main(void)
{
cin>>n;
for(int i=;i<=n;i++)
scanf("%lf%lf",&pt[i].x,&pt[i].y);
for(int i=;i<=;i++)
pt[i+n]=pt[i];
for(int i=;i<=n;i++)
{
ta.s=pt[i],ta.e=pt[i+];
ans=min(ans,ta.dis(pt[i+])/2.0);
}
printf("%.8f\n",ans);
return ;
}
Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) D. Volatile Kite的更多相关文章
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)(A.思维题,B.思维题)
A. Vicious Keyboard time limit per test:2 seconds memory limit per test:256 megabytes input:standard ...
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) C Voltage Keepsake
地址:http://codeforces.com/contest/801/problem/C 题目: C. Voltage Keepsake time limit per test 2 seconds ...
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) 题解【ABCDE】
A. Vicious Keyboard 题意:给你一个字符串,里面只会包含VK,这两种字符,然后你可以改变一个字符,你要求VK这个字串出现的次数最多. 题解:数据范围很小,暴力枚举改变哪个字符,然后c ...
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)
A 每次可以换一个或不换,暴力枚举位置即可 B 模拟 C 二分答案.. 边界可以优化r=totb/(tota-p),二分可以直接(r-l>=EPS,EPS不要太小,合适就好),也可以直接限定二分 ...
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) A B C D 暴力 水 二分 几何
A. Vicious Keyboard time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) 菜鸡只会ABC!
Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) 全场题解 菜鸡只会A+B+C,呈上题解: A. Bear and ...
- Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) C. Bear and Different Names 贪心
C. Bear and Different Names 题目连接: http://codeforces.com/contest/791/problem/C Description In the arm ...
- Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) B - Bear and Friendship Condition 水题
B. Bear and Friendship Condition 题目连接: http://codeforces.com/contest/791/problem/B Description Bear ...
- 【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps
我们要统计的答案是sigma([L/K]),L为路径的长度,中括号表示上取整. [L/K]化简一下就是(L+f(L,K))/K,f(L,K)表示长度为L的路径要想达到K的整数倍,还要加上多少. 于是, ...
随机推荐
- Logstash zabbix 插件
zabbix 监控 logstash 安装社区扩展包wget http://download.elasticsearch.org/logstash/logstash/logstash-contrib- ...
- HDU2586.How far away ?——近期公共祖先(离线Tarjan)
http://acm.hdu.edu.cn/showproblem.php?pid=2586 给定一棵带权有根树,对于m个查询(u,v),求得u到v之间的最短距离 那么仅仅要求得LCA(u,v),di ...
- C#------SortedLIst键值对的使用方法
方法: SortedList sf = new SortedList(); sf.Add(, "广州"); sf.Add(, "江门"); sf.Add(, & ...
- 分页技巧_改进JSP页面中的公共分页代码_实现分页时可以有自定义的过滤与排序条件
分页技巧__改进JSP页面中的公共分页代码 自定义过滤条件问题 只有一个url地址不一样写了很多行代码 public>>pageView.jspf添加 分页技巧__实现分页时可以有自定义的 ...
- GSAP 官方文档(结贴)
好久没写GSAP的教程的(其实我也不懂哈哈),国内也没什么人用,不对动画要求特别高的话,其实也没必要用GSAP,现在工作上没用到这个东西,也懒得写了,所以有问题的话去找一下greensock的官方文档 ...
- Java Web项目--使用Servlet生成一个页面
为了生成一个servlet对应的网页.我们需要新建一个web.xml,其中将会放置servlet的相关信息.web.xml文件放置在WebContent/WEB-INF/目录下.(我们在Eclipe中 ...
- Docker修改时区
简介 docker容器打日志时间滞后8小时 方法 启动时修改时区 Docker修改默认时区 已启动的容器修改时区 进入容器docker exec -i -t [CONTAINNER] /bin/bas ...
- hibernate中持久化对象的状态
持久化对象有以下几种状态: 临时对象(Transient): 在使用代理主键的情况下, OID 通常为 null 不处于 Session 的缓存中 在数据库中没有对应的记录 持久化对象(也叫”托管 ...
- Morphia - mongodb之ORM框架
一.简介 二.注解 1.@Entity 2.@Id3.@Indexed4.@Embedded5.@Transient和@Property6.@Reference 三.示例 四.参考资料 Morphia ...
- glibc-2.23_int_malloc_流程浅析