BZOJ 1013

题链

脑抽了一下,写了个爬山算法找答案。洛谷上一直70分。退火还写残了。(有大佬会退火做法的话,欢迎讨论)

#include<bits/stdc++.h>
#define esp 5e-5
#define dla 0.8
#define kkk 1
#define db long double
#define random rrr
using namespace std;
db ask,len[17],sum,f[17][17],ans[17],T,ite,af,dE,a[17],g;
int n;
inline db check() { //不要问我这个check函数哪里来的,我是一个一个函数试过来的。
    ask=0; sum=0;
    for (int i=1;i<=n+1;i++)  {
     len[i]=0;
     for (int j=1;j<=n;j++) len[i]=len[i]+(f[i][j]-ans[j])*(f[i][j]-ans[j]); 
     sum=sum+len[i];
    } sum=sum/(n+1);
    for (int i=1;i<=n+1;i++) ask+=(len[i]-sum)*(len[i]-sum);
    return sqrt(ask);
}
inline db random() {
    return 1.0*(rand()%10001)/(10000);
}
int main () {
//    freopen("a.in","r",stdin);
    char*p =new char;
    srand((unsigned long long)p);
    scanf("%d",&n);
//    cerr<<random()<<endl;
    for (int i=1;i<=n+1;i++) 
     for (int j=1;j<=n;j++) 
      scanf("%Lf",&f[i][j]);
    T=10000; af=check();
    for (int i=1;i<=n;i++) a[i]=i;
    while (T>esp) {
        g=5;
        while (g--) {
        random_shuffle(a+1,a+n+1);
        for (int t=1,i;t<=n;t++) {
          i=a[t];
          ans[i]+=T; ite=check();//  dE=(-ite+af)*kkk/T;
           if (ite<af
           //||exp(dE/T)>random()
           ) {af=ite;continue;}
          ans[i]-=2*T; ite=check();// dE=(-ite+af)*kkk/T;
           if (ite<af
           //||exp(dE/T)>random()
           ) {af=ite;continue;}
          ans[i]+=T;
            } 
        }
        T=T*dla;
    }
    for (int i=1;i<=n;i++) printf("%.3Lf ",ans[i]);
}

然后想到是高斯消元,我们把式子两两相等,就消去了二次项。

#include<bits/stdc++.h>
#define db long double
#define N 17
using namespace std;
db f[N][N],l[N][N];
int n;
void init() {
    scanf("%d",&n);
    for (int i=0;i<=n;i++)
     for (int j=1;j<=n;j++) {
         scanf("%Lf",f[i]+j);
         if (i) {
             l[i][j]=2*(f[i][j]-f[i-1][j]);
             l[i][n+1]+=f[i][j]*f[i][j]-f[i-1][j]*f[i-1][j];
         }
     }
}
void gao(){
    for (int i=1;i<=n;i++) {
        int t=i;
        for (int j=i+1;j<=n;j++) if (fabs(l[t][i])<fabs(l[j][i])) t=j;
        if (t^i) for (int j=1;j<=n+1;j++) swap(l[i][j],l[t][j]);
        for (int j=i+1;j<=n;j++) {
            db x=l[j][i]/l[i][i];
            for (int k=i;k<=n+1;k++) l[j][k]-=x*l[i][k];
        }
    }
    for (int i=n;i;i--) {
        for (int j=i+1;j<=n;j++) l[i][n+1]-=l[i][j]*l[j][n+1];
        l[i][n+1]/=l[i][i];
    }
}
int main () {
    init();
    gao();
    for (int i=1;i<=n;i++)
     printf("%.3Lf%c",l[i][n+1],i==n?'\n':' ');
}

 

posted @ 2018-02-05 09:57  泪寒之雪  阅读(158)  评论(0编辑  收藏  举报