题目来源:
http://poj.org/problem?id=3525
分析:
题意:给定一个凸多边形,求多边形中距离边界最远的点到边界的距离。
思路 : 每次将凸多边形每条边往里平移d,判断是否存在核;二分d即可。
多边形边上的点(x , y)往里平移d 后的 坐标: s , e 为向量的 起点和终点, len 为起点和终点的距离, h 为平移的距离
x' = x + dx
y' = y + dy
dx = ( s.y - e.y ) / len * h ,( 原理 是 利用 三角形的相似比 )
dy = ( e.x - s.x ) / len * h ;
代码如下:
using namespace std ; const double EPS = 1e-10 ; const int Max_N = 105 ; double add(double a, double b){ return (fabs(a + b) < EPS * (fabs(a) + fabs(b))) ? 0 : (a + b) ; } struct Point{ double x, y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point a){ return Point(add(x , -a.x) , add(y , -a.y)) ; } Point operator + (Point a){ return Point(add(x ,a.x) , add(y , a.y)) ; } double operator ^(Point a){ return add(x * a.y , - y * a.x) ; } Point operator *(double d){ return Point(x * d, y * d) ; } double dist(Point a){ return sqrt( add((x - a.x) * (x - a.x) , (y - a.y)*(y - a.y) ) ) ; } }; struct Line{ Point st, ed; Line(){} Line(Point st, Point ed):st(st),ed(ed){} bool onRight(Point a){ // 点在线右边 return ((ed - st)^(a - st)) < 0 ; } bool parallel(Line l){ return ((ed - st)^(l.ed - l.st)) == 0 ; } Point CrossNode(Line l){ double d1 = (l.ed - l.st)^(l.st - st) ; double d2 = (l.ed - l.st)^(ed - st) ; return st + (ed - st)*(d1 / d2) ; } double jijiao(){ return atan2(ed.y - st.y , ed.x - st.x) ; } }; bool operator < (Line l , Line r){ double lp = l.jijiao() ; double rp = r.jijiao() ; if(fabs(lp - rp) > EPS) return lp < rp ; return ((l.st - r.st)^(r.ed - r.st)) < 0 ; } Line dequeue[Max_N] ; int halfPanelCross(Line line[] , int ln){ int i, tn ; sort(line , line + ln ) ; for(i = tn = 1; i < ln ; i++){ if( fabs(line[i].jijiao() - line[i - 1].jijiao()) > EPS ) line[tn ++] = line[i] ; } ln = tn ; int bot = 0 , top = 1 ; dequeue[0] = line[0] ; dequeue[1] = line[1] ; Point topcross ,botcross ; for(i = 2 ; i < ln ; i++){ if(dequeue[top].parallel(dequeue[top - 1]) || dequeue[bot].parallel(dequeue[bot + 1]) ) return 0 ; while(bot < top && line[i].onRight(topcross = dequeue[top].CrossNode(dequeue[top - 1]))) top -- ; while(bot < top && line[i].onRight( botcross = dequeue[bot].CrossNode(dequeue[bot + 1]))) bot ++ ; dequeue[++ top] = line[i] ; } while(bot < top && dequeue[bot].onRight(topcross = dequeue[top].CrossNode(dequeue[top - 1]))) top -- ; while(bot < top && dequeue[top].onRight(botcross = dequeue[bot].CrossNode(dequeue[bot + 1]))) bot ++ ; if(top <= bot + 1) return 0 ; return 1; } Line tmp[Max_N] ; Line List[Max_N] ; void ploygonChange(double h, int ln){ double len , dx ,dy ; for(int i= 0 ; i < ln ; i++){ len = List[i].ed.dist(List[i].st) ; dx = (List[i].st.y - List[i].ed.y) / len * h ; dy = (List[i].ed.x - List[i].st.x) / len * h ; tmp[i].st.x = List[i].st.x + dx ; tmp[i].st.y = List[i].st.y + dy ; tmp[i].ed.x = List[i].ed.x + dx; tmp[i].ed.y = List[i].ed.y + dy ; } } double BinSearch(int ln){ double l , r, mid ; l = 0.0 , r = 20000.0 ; while(l + EPS < r){ mid = (l + r) * 0.5 ; ploygonChange(mid , ln ) ; if(halfPanelCross(tmp , ln)) l = mid ; else r = mid ; } return l; } int main(){ int n; Point p[Max_N] ; while(scanf("%d" , &n) && n){ for(int i = 0 ; i < n ; i++) scanf("%lf%lf" , &p[i].x , &p[i].y) ; for(int i = 0 ; i < n ; i++) List[i] = Line(p[i] , p[(i+1) % n]) ; double tt = BinSearch(n) ; printf("%.6lf " ,tt) ; } return 0; }