如下两份代码一模一样,为何跑出来结果大相径庭?
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
using namespace std;
const int N=12;
double p[N][N];
int n,m;
double dist(double a[],double b[]){//不是欧几里得距离,最后没有开根(为了精度
double res=0;
for(int i=1;i<=n;i++)
res+=1.0*(a[i]-b[i])*(a[i]-b[i]);
return res;
}
double rand(double l,double r){
l=max(l,-2e4);
l=min(l,2e4);
r=max(r,-2e4);
r=min(r,2e4);
return 1.0*rand()/RAND_MAX*(r-l)+l;
}
double ans[N],Md=1e18;
double calc(double k[]){
double dis[N];
for(int i=1;i<=m;i++)
dis[i]=dist(k,p[i]);
double avg=0;
for(int i=1;i<=m;i++)
avg+=dis[i];
avg/=m;
double res=0;
for(int i=1;i<=m;i++)
res+=(avg-dis[i])*(avg-dis[i]);
if(res<Md){
Md=res;
for(int i=1;i<=n;i++)
ans[i]=k[i];
}
return res;
}
void simulate_anneal(){
double k[N],q[N];
double now=calc(k);
double nex;
for(double T=2e4;T>=1e-6;T*=0.9996){
for(int i=1;i<=n;i++)
q[i]=rand(k[i]-T,k[i]+T);
nex=calc(q);
double dt=nex-now;
if(exp(-dt/T)>rand(0,1)){
for(int i=1;i<=n;i++)
k[i]=q[i];
now=nex;
}
}
}
int main(){
scanf("%d",&n);
m=n+1;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
scanf("%lf",p[i]+j);
while(1.0*clock()/CLOCKS_PER_SEC<0.9)
simulate_anneal();
for(int i=1;i<=n;i++)
printf("%.3lf ",ans[i]);
return 0;
}
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 15;
int n;
double p[N][N], cur[N], ne[N], ans[N], minv = 1e18;
double rand(double l, double r) {
l = min(l, 2e4);
r = min(r, 2e4);
l = max(l, -2e4);
r = max(r, -2e4);
return (double)rand() / RAND_MAX * (r - l) + l;
}
double dist(double a[], double b[]) {
double res = 0;
for (int i = 0; i < n; i ++ )
res += (a[i] - b[i]) * (a[i] - b[i]);
return res;
}
int m;
double calc(double k[]){
double dis[N];
for(int i=0;i<m;i++)
dis[i]=dist(k,p[i]);
double avg=0;
for(int i=0;i<m;i++)
avg+=dis[i];
avg/=m;
double res=0;
for(int i=0;i<m;i++)
res+=(avg-dis[i])*(avg-dis[i]);
if(res<minv){
minv=res;
for(int i=0;i<n;i++)
ans[i]=k[i];
}
return res;
}
// double calc(double a[]) {
// double avg = 0;
// for (int i = 0; i <= n; i ++ ) {
// double sum = 0;
// for (int j = 0; j < n; j ++ )
// sum += (p[i][j] - a[j]) * (p[i][j] - a[j]);
// dist[i] = sum;
// avg += sum;
// }
// avg /= n + 1;
// double res = 0;
// for (int i = 0; i <= n; i ++ )
// res += (avg - dist[i]) * (avg - dist[i]);
// if (res < minv) {
// minv = res;
// for (int i = 0; i < n; i ++ )
// ans[i] = a[i];
// }
// return res;
// }
void saa() {
for (int i = 0; i < n; i ++ ) cur[i] = rand(-2e4, 2e4);
for (double t = 2e4; t > 1e-15; t *= 0.9997) {
for (int i = 0; i < n; i ++ )
ne[i] = rand(cur[i] - t, cur[i] + t);
double x = calc(cur), y = calc(ne);
double dt = y - x;
if (exp(-dt / t) > rand(0, 1))
for (int i = 0; i < n; i ++ )
cur[i] = ne[i];
}
}
int main() {
srand(time(0));
scanf("%d", &n);
m=n+1;
for (int i = 0; i <= n; i ++ )
for (int j = 0; j < n; j ++ )
scanf("%lf", &p[i][j]);
while ((double)clock() / CLOCKS_PER_SEC < 0.9) saa();
for (int i = 0; i < n; i ++ ) printf("%.3lf ", ans[i]);
return 0;
}