USACO6.4.2 Electric Fences(fence3)

来源:互联网 发布:苏州火易网络招聘 编辑:程序博客网 时间:2024/06/05 11:29

“模拟退火”,也是胡整算法吧,不过确实很好用

题目范围不大,精度要求不高,枚举,将整个连续空间离散分成1000个每个相距0.1的点,枚举每个点,能找到答案,复杂度高,是可以优化的

二分,每次枚举9个点 ( 正方形平均的9个点 ),找到最有点后再以这个点为九个点的中心点缩小步长再尝试9个点,直到枚举的两点间相差<0.01

求出一个点到某线段的最短距离,要分两种情况:

一是这个点做垂线会落到这个线段上,这种情况用差乘求出这个点与线段构成的三角形面积*2,然后再除以这个线段的长度就是垂线的长度:

二是这个点对线段做出的垂线在线段外,那么最短的距离只可能是到线段两个端点距离的最短那个。判断钝角三角形(x1^2+x2^2<x3^2,代表x1与x2的夹角是钝角)


/*PROG:fence3ID:xsy97051LANG:C++*/#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;#define INF 2000000005    struct node  {      double x0,y0,x1,y1,len;         }line[152];  double ansx,ansy,ans,len,step;double MaxX,MaxY,StartX,StartY; double dis(node a,double x,double y)  {      double x1,y1,x2,y2;      x1=(x-a.x0)*(x-a.x0)+(y-a.y0)*(y-a.y0);      x2=(x-a.x1)*(x-a.x1)+(y-a.y1)*(y-a.y1);      if(x1-x2-a.len*a.len>-0.001 || x2-x1-a.len*a.len>-0.001)       {if(x1<x2) return sqrt(x1);     elsereturn sqrt(x2);           }    x1=x-a.x0;    y1=y-a.y0;    x2=a.x1-a.x0;    y2=a.y1-a.y0;        double tep=x1*y2-x2*y1;      if(tep<0)tep=-tep;          return tep/a.len;  }  int main(){freopen("fence3.in","r",stdin);freopen("fence3.out","w",stdout);StartX=StartY=INF;      MaxX=MaxY=-INF;     int n;    cin>>n;    for(int i=1;i<=n;i++)    {scanf("%lf%lf%lf%lf",&line[i].x0,&line[i].y0,&line[i].x1,&line[i].y1);          line[i].len=sqrt((line[i].x0-line[i].x1)*(line[i].x0-line[i].x1)+(line[i].y0-line[i].y1)*(line[i].y0-line[i].y1));        if(line[i].x1<line[i].x0)              swap(line[i].x1,line[i].x0);           if(line[i].y1<line[i].y0)          swap(line[i].y1,line[i].y0);                  if(line[i].x1>MaxX) MaxX=line[i].x1;        if(line[i].x0<StartX) StartX=line[i].x0;        if(line[i].y1>MaxY) MaxY=line[i].y1;        if(line[i].y0<StartY) StartY=line[i].y0;    }    if(MaxY>MaxX)len=MaxY/2;      elselen=MaxX/2;           ans=INF;    ans*=ans;        while(len>0.01)    {        step=len/4;          MaxX=StartX+len; MaxY=StartY+len;for(double x=StartX;x<=MaxX;x+=step)              for(double y=StartY;y<=MaxY;y+=step)              {double now=0;                for(int i=1;i<=n;i++)                  {                      now+=dis(line[i],x,y);                      if(now>ans) break;                     }                     if(now<ans)                  {                      ans=now;                      ansx=x;                       ansy=y;                       }            }        StartX=ansx-step/2;          StartY=ansy-step/2;           len/=2;    }printf("%.1lf %.1lf %.1lf\n",ansx,ansy,ans);      return 0;}


0 0