HDU 3007

最小圆覆盖

#include<bits/stdc++.h>
#define N 1000010
#define INF 0x3f3f3f3f
#define eps 1e-7
#define pi 3.141592653589793
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
 
struct point{  
    double x,y;
} a[510];  
int n;  
double D(point a,point b){  
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}  

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_real_distribution<double> dis(-1,1);

double ansx,ansy;

double solve(double X){  
    double step=1e3,x=0,y=0;
    point p;
    double ans=X;
    while(step>1e-8){  
        p.x=x+dis(rng)*step;p.y=y+dis(rng)*step;
        double tm=0;
        for(int i=0; i<n;i++) tm=max(tm,D(p,a[i]));
        if (tm<ans){
            ans=tm;
            ansx=x=p.x,ansy=y=p.y; 
        }else 
        if (exp((tm-ans)/step)<(dis(rng)+1)/2) x=p.x,y=p.y;
        step*=0.98;  
    }  
    return ans;  
}  

int main()  
{ 
    while(~scanf("%d",&n))  
    {  
        if (!n) break;
        for(int i=0; i<n; i++)scanf("%lf%lf",&a[i].x,&a[i].y);  
        double ans=1e3;
        ans=min(ans,solve(ans));
        printf("%.2f %.2f %.2f\n",ansx,ansy,ans);  
    }  
    return 0;  
}

HDU 3644

多边形内能否嵌套一个给定半径的圆

其实就是看多边形里嵌套的最大圆的半径

牛逼的地方,在于多个点同时跑退火,起始是每条线段的中点,然后随机角度,在该角度增加 s t e p step step,还有个牛逼的地方,对于当前 s t e p step step 不能只随机1次,因为可能随机到多边形外部,所以要多随机几次,最后牛逼的地方,降温系数不是通常的 0.98、0.99 只需要 0.8 左右,没错只要 0.8!!!

模拟退火水好深

#include<bits/stdc++.h>
#define N 1000010
#define INF 0x3f3f3f3f
#define eps 1e-5
#define pi 3.141592653589793
#define mod 998244353
// #define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
 
inline int dcmp(double x){if (x<=-eps) return -1;else return x>=eps?1:0;}

struct Point{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){ }
}a[60],c[60];
double d[60];
typedef Point Vector;
Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
Vector operator * (Vector a,double b){return Vector(a.x*b,a.y*b);}
Vector operator / (Vector a,double b){return Vector(a.x/b,a.y/b);}
bool operator == (Vector a,Vector b){return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;}
double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}  //点积
double Length(Vector a){return sqrt(Dot(a,a));}
double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;} //叉积

//点到线段的距离,p到线段ab的距离,若距离不存在,返回pa,pb中较短的线段的距离
double DistanceToSegment(Point p,Point a,Point b)
{
    if (a==b)return Length(p-a);
    Vector v1=b-a,v2=p-a,v3=p-b;
    if (dcmp(Dot(v1,v2))<0)return Length(v2);
    else if (dcmp(Dot(v1,v3))>0)return Length(v3);
    else return fabs(Cross(v1,v2))/Length(v1);
}
//点在线段上(包含端点),在为 1 ,不在为 0
bool isPointOnSegment(Point P,Point A,Point B){
    return dcmp(Cross(A-P,B-P))==0 && dcmp(Dot(A-P,B-P))<=0;  // 不包含端点时为 <0
}
//点在多边形内判定
int isPointInPolygon(Point p,Point* poly,int n)
{
    int wn=0;
    for(int i=0;i<n;i++){
        if(isPointOnSegment(p,poly[i],poly[(i+1)%n])) return -1;//在边界上
        int k=dcmp(Cross(poly[(i+1)%n]-poly[i], p-poly[i]));
        int d1=dcmp(poly[i].y-p.y);
        int d2=dcmp(poly[(i+1)%n].y-p.y);
        if(k>0 && d1<=0 && d2>0) wn++;
        if(k<0 && d2<=0 && d1>0) wn--;
    }
    if(wn!=0) return 1; //在内部
    return 0;           //在外部
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
double solve(int n){  
    double step=1e3;
    Point p;
    while(step>1e-5){  
        for(int i=0;i<n;i++)
            for(int j=0;j<5;j++){
                double ang=rng();
                p.x=c[i].x+step*cos(ang);p.y=c[i].y+step*sin(ang);
                if(isPointInPolygon(p,a,n)==1){
                    double tm=1e3;
                    for(int i=0;i<n;i++) tm=min(tm,DistanceToSegment(p,a[i],a[i+1]));
                    if (tm>d[i])c[i]=p,d[i]=tm;
                }
            } 
        step*=0.75;  
    }  
    return *max_element(d,d+n);  
}  

int main()  
{ 
    int n; double r;
    while(~scanf("%d",&n))  
    {  
        if (!n) break;
        for(int i=0; i<n; i++)scanf("%lf%lf",&a[i].x,&a[i].y);  
        scanf("%lf",&r);
        a[n]=a[0]; 
        for(int i=0;i<n;i++) c[i]=(a[i]+a[i+1])/2,d[i]=0;
        double ans=solve(n);
        if(dcmp(ans-r)>=0) puts("Yes");else puts("No");
    }  
    return 0;  
}

HDU 5017

椭球面上找距离原点最近的点
更新 x , y x,y x,y,解二元一次方程算出 z z z ,更新最优值即可

#include<bits/stdc++.h>
#define N 1000010
#define INF 0x3f3f3f3f
#define eps 1e-5
#define pi 3.141592653589793
#define mod 998244353
// #define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
 
inline int dcmp(double x){if (x<=-eps) return -1;else return x>=eps?1:0;}

double a,b,c,d,e,f;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

double slove(){
    double x=sqrt(1/a),y=0,z;double ans=x;
    double step=2,tx,ty;
    while(step>1e-9){
        for(int i=0;i<5;i++){
            double ang=rng();
            tx=x+step*cos(ang),ty=y+step*sin(ang);
            double A=c,B=d*ty+e*tx,C=a*tx*tx+b*ty*ty+f*tx*ty-1;
            double delta=B*B-4.0*A*C,tm;
            if (delta<0) continue;
            z=(-B-sqrt(delta))/A/2;
            tm=sqrt(z*z+tx*tx+ty*ty);
            if (tm<ans) ans=tm,x=tx,y=ty;
            z=(-B+sqrt(delta))/A/2;
            tm=sqrt(z*z+tx*tx+ty*ty);
            if (tm<ans) ans=tm,x=tx,y=ty;
        }
        step*=0.98;
    }
    return ans;
}
int main()
{
    while(~scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)){
        double ans=10;
        for(int i=0;i<2;i++) ans=min(ans,slove());
        printf("%.6f\n",ans);
    }
    return 0;
}

HDU 2899

求一个函数最小值

#include<bits/stdc++.h>
#define N 50010
#define INF 0x3f3f3f3f
#define eps 1e-7
#define pi 3.141592653589793
#define mod 998244353
// #define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_real_distribution<double> dis(-1.0,1.0);
double y;
inline double f(double x){
    return pow(x,7)*6+pow(x,6)*8+pow(x,3)*7+pow(x,2)*5-y*x;
}

double slove(){
    double step=50,x=50,ans=f(x);
    while(step>1e-15){
        for(int i=0;i<5;i++){
            double tmp=x+step*dis(rng);
            if (tmp<0||tmp>100) continue;
            double tt=f(tmp);
            if (tt<ans)
                ans=tt,x=tmp;
        }
        step*=0.99;
    }
    return ans;
}
int main(int argc, char const *argv[])
{
    int T;sc(T);
    while(T--){
        scanf("%lf",&y);
        printf("%.4f\n",slove());
    }
    return 0;
}

HDU 3932

#include<bits/stdc++.h>
#define N 50010
#define INF 0x3f3f3f3f
#define eps 1e-7
#define pi 3.141592653589793
#define mod 998244353
// #define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_real_distribution<double> dis(-1.0,1.0);
double X,Y,x[N],y[N],ax,ay; int n;
int dx[]={0,1,1,1,0,-1,-1,-1};
int dy[]={1,1,0,-1,-1,-1,0,1};

double f(double p,double q){
    double res=0;
    for(int i=0;i<n;i++){
        double t=sqrt((p-x[i])*(p-x[i])+(q-y[i])*(q-y[i]));
        res=max(res,t);
    } return res;
}

double slove(){
    double step=10000; ax=0,ay=0;double ans=f(ax,ay);
    while(step>1e-15){
        for(int i=0;i<16;i++){
            double k=rng();
            double tx=ax+step*cos(k),ty=ay+step*sin(k);
            if (tx<0||tx>X||ty<0||ty>Y) continue;
            double tt=f(tx,ty);
            if (tt<ans)
                ans=tt,ax=tx,ay=ty;
        }
        step*=0.95;
    }
    return ans;
}
int main(int argc, char const *argv[])
{
    while(~scanf("%lf%lf%d",&X,&Y,&n)){
        for(int i=0;i<n;i++) scanf("%lf%lf",&x[i],&y[i]);
        double ans=slove();
        printf("(%.1f,%.1f).\n%.1f\n",ax,ay,ans);
    }
    return 0;
}