从自己的直观感觉上,应该目标函数是一个单峰函数,因此不需要用到模拟退火的思想----以一定的概率接受更差解,只需爬山即可。这玩意儿太玄学了,大概是刚学,还不太理解这个过程吧。自己写的爬山一会儿在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;
}