首页 > 代码库 > BZOJ 3680 吊打XXX(模拟退火)

BZOJ 3680 吊打XXX(模拟退火)

一个很好玩的概率算法。

总是接受比当前解的邻域里更优的解,以一个类似于退火的概率接受邻域里次的解。

 

技术分享
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi 3.1415926535
# define eps 1e-3
# define MOD 1000000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
void Out(int a) {
    if(a<0) {putchar(-); a=-a;}
    if(a>=10) Out(a/10);
    putchar(a%10+0);
}
const int N=100005;
//Code begin...

struct Node{double x, y, w;}now, ans, point[N];
int n;
double total=1e16;

inline double Dist(Node a, Node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline double Statistic(Node p){
    double res=0;
    FO(i,0,n) res+=Dist(p,point[i])*point[i].w;
    if (res<total) total=res, ans=p;
    return res;
}
inline double Rand(){return (rand()%1000+1)/1000.0;}
int main ()
{
    Node tmp;
    srand(10086);
    scanf("%d",&n);
    FO(i,0,n) scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].w), now.x+=point[i].x, now.y+=point[i].y, now.w+=point[i].w;
    now.x/=n; now.y/=n; now.w/=n;
    double T=100000.0, alpha, sub;
    while (T>eps) {
        alpha=2.0*pi*Rand();
        tmp.x=now.x+T*cos(alpha); tmp.y=now.y+T*sin(alpha);
        sub=Statistic(now)-Statistic(tmp);
        if (sub>=0||exp(sub/T)>=Rand()) now=tmp;
        T*=0.94;
    }
    T=0.001;
    FOR(i,1,1000) {
        alpha=2.0*pi*Rand();
        tmp.x=ans.x+T*cos(alpha)*Rand(); tmp.y=ans.y+T*sin(alpha)*Rand();
        Statistic(tmp);
    }
    printf("%.3lf %.3lf\n",ans.x,ans.y);
    return 0;
}
View Code

 

BZOJ 3680 吊打XXX(模拟退火)