【退火!!!退火!!!】poj2420

来源:互联网 发布:js 数组 slice 编辑:程序博客网 时间:2024/04/29 12:48

http://poj.org/problem?id=2420
题目大意就是说给你n个点让你求一个到所有点的和最短的点(n<100)
然后很明显是个搜索的题,感觉爬山什么的也可以做
但是退火大法做不是更233吗,于是就退火退火……
退火就不再多说,这里想说一个类似于离散化点的做法参考了黄学长orz

程序如下:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<set>#include<queue>#include<algorithm>#include<vector>#include<cstdlib>#include<cmath>#include<ctime>#include<stack>#define INF 2100000000#define ll long long#define clr(x)  memset(x,0,sizeof(x))#define maxclr(x)  memset(x,127,sizeof(x))using namespace std;#define M 105struct point{    double x,y;    point(double x=0,double y=0):x(x),y(y){}}a[M],t[M];const int tim=100;double maxx,maxy,minx,miny,ans=1E100,T,best[tim+1];double sumx,sumy,sx,sy;const double eps=1E-8;const double TUI=0.9;const double T_min=1e-4;inline point read(){    point ret=0;    char c;    while(!(c>='0'&&c<='9'))        c=getchar();    while(c>='0'&&c<='9')    {        ret.x=(c-'0')+ret.x*10;        c=getchar();    }    maxx=max(maxx,ret.x);    minx=min(minx,ret.x);    while(!(c>='0'&&c<='9'))        c=getchar();    while(c>='0'&&c<='9')    {        ret.y=(c-'0')+ret.y*10;        c=getchar();    }    maxy=max(maxy,ret.y);    miny=min(miny,ret.y);    sumx+=ret.x;    sumy+=ret.y;    return ret;}double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int n;double rand01(){    double t1=(double)(rand()%1000)/(double)1000,           t2=(double)(rand()%1000)/(double)1000;    double r=t1+t2*0.001;    return r;}double randd(double l,double r){    return l+(r-l)*rand01();}point rand_point(point a,double b){    double l=a.x-b,r=a.x+b;    double x=randd(l,r);    l=a.y-b;r=a.y+b;    double y=randd(l,r);    return point(x,y);}double get_ans(point x){    double ret=0;    for(int i=1;i<=n;i++)        ret+=dis(x,a[i]);    return ret;}void tuihuo(){    T=max(maxx-minx,maxy-miny);    t[1]=point(maxx,maxy);    t[2]=point(maxx,miny);    t[3]=point(minx,maxy);    t[4]=point(minx,miny);    t[5]=point((maxx+minx)/2,(maxy+miny)/2);    t[6]=point(sumx/(double)n,sumy/(double)n);    maxclr(best);    best[0]=0;    for(int i=7;i<=tim;i++)        t[i]=rand_point(t[5],T);    for(int i=1;i<=tim;i++)        best[i]=get_ans(t[i]);    while(T>T_min)    {        for(int i=1;i<=tim;i++)        {            sx=0,sy=0;            for(int j=1;j<=n;j++)//这个就是黄学长orz的离散做法            {                double d=dis(t[i],a[j]);                if(d>-eps&&d<eps)continue;                sx+=(a[j].x-t[i].x)/d;                sy+=(a[j].y-t[i].y)/d;            }            //sx/=n;这两排加不加都可以,我感觉应该加上去的            //sy/=n;            point now=point(t[i].x+T*sx,t[i].y+T*sy);            double temp=get_ans(now);            if(temp<best[i]||exp(best[i]-temp)/T>rand01())            {                t[i]=now;                best[i]=temp;            }        }        T*=TUI;    }    for(int i=1;i<=tim;i++)        ans=min(ans,best[i]);}int main(){    freopen("in.txt","r",stdin);    srand((unsigned)time(0));    cin>>n;    for(int i=1;i<=n;i++)        a[i]=read();    tuihuo();    printf("%.0f",ans);}

大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。

0 0
原创粉丝点击