UVA10228 A Star not a Tree?

UVA10228 A Star not a Tree?

题意翻译

给定一个N边形所有顶点坐标x,y,求其费马点到所有顶点距离和

费马点是指到多边形所有顶点距离和最小的点

输入

第一行为T, T组数据

第二行正整数N,其后N行,每行两个整数x,y。

输出

每行一个数,为所求距离和,精确到整数(每组数据要多输出一个换行,最后一组不用)

Translated by @BeyondOI

输入输出样例

输入 #1

1
4
0 0
0 10000
10000 10000
10000 0

输出 #1

28284

​ 这道题做法有三分和模拟退火,我用的是模拟退火。

​ 我的模拟退火板子(感谢Tethys的友情支持):

void SA() {
    double temp = 3000;
    double x = ax , y = ay;
    while(temp > eps) {
        double x1 = x + ((rand() << 1) - RAND_MAX) * temp;
        double y1 = y + ((rand() << 1) - RAND_MAX) * temp;
        double now_ans = calc(x1, y1);
        double del = now_ans - ans;
        if(del < 0) {
            ax = x1, ay = y1;
            x = x1, y = y1; 
            ans = now_ans;
        }
        else 
            if(exp(- del / temp) * RAND_MAX > rand()) 
                x = x1, y = y1;
        temp *= dwtem;
    }
}

​ temp:温度;

​ dwtem :每次降温多少;

​ del :\(\Delta\)E;

​ 公式:\(P(\Delta E) = e ^ {\frac{\Delta E}{T}}\)

#include <bits/stdc++.h>
    
using namespace std;
    
inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}
    
const int N = 105;
const double eps = 1e-12;
const double dwtem = 0.996;
int n, T;
double ax, ay, ans, sumx, sumy;
struct node { double x, y; } a[N];

double calc(double x, double y) {
    double res = 0;
    for(int i = 1;i <= n; i++) 
        res += sqrt((x - a[i].x) * (x - a[i].x) + (y - a[i].y) * (y - a[i].y));
    return res;
}

void SA() {
    double temp = 3000;
    double x = ax , y = ay;
    while(temp > eps) {
        double x1 = x + ((rand() << 1) - RAND_MAX) * temp;
        double y1 = y + ((rand() << 1) - RAND_MAX) * temp;
        double now_ans = calc(x1, y1);
        double del = now_ans - ans;
        if(del < 0) {
            ax = x1, ay = y1;
            x = x1, y = y1; 
            ans = now_ans;
        }
        else 
            if(exp(- del / temp) * RAND_MAX > rand()) 
                x = x1, y = y1;
        temp *= dwtem;
    }
}

int main() {
    
    srand(1e9 + 7);
    T = read();
    for(int i = 1;i <= T; i++) {
        n = read();
        sumx = sumy = 0; ans = 1e11;
        for(int j = 1;j <= n; j++) {
            scanf("%lf %lf", &a[j].x, &a[j].y);
            sumx += a[j].x; sumy += a[j].y;
        }
        ax = sumx / n; ay = sumy / n;
        for(int j = 1;j <= 5; j++) SA();
        printf("%.0lf\n", ans);
        if(i != T) printf("\n");
    }

    return 0;
}

(感觉模拟退火好迷呀,都是rand)

posted @ 2020-09-02 06:15  C锥  阅读(144)  评论(0编辑  收藏  举报