从自己的直观感觉上,应该目标函数是一个单峰函数,因此不需要用到模拟退火的思想----以一定的概率接受更差解,只需爬山即可。这玩意儿太玄学了,大概是刚学,还不太理解这个过程吧。自己写的爬山一会儿在bzoj可以过,洛谷过不了,修改了一些参数后又恰恰相反,而且还有精度低时洛谷可以过,把精度调高反而wa了,很是玄乎。
写法一:
#include<bits/stdc++.h>
using namespace std;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
int n,x[10005],y[10005],w[10005];
double T=200000,T_min=1e-4,delta=0.98;
double nowx,nowy,now;
double nextx,nexty,next;
double calc(double px,double py)
{
double pos=0;
for(int i=0;i<n;i++)pos+=w[i]*sqrt((px-x[i])*(px-x[i])+(py-y[i])*(py-y[i]));
return pos;
}
int main()
{
//freopen("input.in","r",stdin);
cin>>n;
for(int i=0;i<n;i++)cin>>x[i]>>y[i]>>w[i];
now=calc(nowx,nowy);
while(T>T_min)
{
int i=rand()%4;
nextx=nowx+dx[i]*T;
nexty=nowy+dy[i]*T;
next=calc(nextx,nexty);
if(next<now)
{
now=next;
nowx=nextx;
nowy=nexty;
}
T*=delta;
}
printf("%.3f %.3f\n",nowx,nowy);
return 0;
}
写法二:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
int n,x[10005],y[10005],w[10005];
double T=192600,T_min=1e-14,delta=0.993;
double nowx,nowy,now;
double nextx,nexty,next;
double calc(double px,double py)
{
double pos=0;
for(int i=0;i<n;i++)pos+=w[i]*sqrt((px-x[i])*(px-x[i])+(py-y[i])*(py-y[i]));
return pos;
}
int main()
{
srand(time(0));
// freopen("input.in","r",stdin);
cin>>n;
for(int i=0;i<n;i++)cin>>x[i]>>y[i]>>w[i];
now=calc(nowx,nowy);
while(T>T_min)
{
double nextx=nowx+(rand()*2-RAND_MAX)*T;
double nexty=nowy+(rand()*2-RAND_MAX)*T;
next=calc(nextx,nexty);
if(next<now)
{
now=next;
nowx=nextx;
nowy=nexty;
}
T*=delta;
}
printf("%.3f %.3f\n",nowx,nowy);
return 0;
}