【基础】随机优化算法

https://codeforces.com/contest/2/problem/C

随机移动算法。

double x[4], y[4], r[4];

double dis(double X, double Y, int id) {
    double len = sqrt(sq(X - x[id]) + sq(Y - y[id]));
    return PI / 2.0 - acos(r[id] / len);
}

double getLoss(double X, double Y) {
    double dis1 = dis(X, Y, 1), dis2 = dis(X, Y, 2), dis3 = dis(X, Y, 3);
    return sq(dis1 - dis2) + sq(dis1 - dis3) + sq(dis2 - dis3);
}

double myRand() {
    return 2.0 * rand() / RAND_MAX - 1.0;
}

void InnerRandomOptimize(double &X, double &Y, double step, int p1, int p2) {
    double curLoss = getLoss(X, Y);
    for(int i = 1; i <= p1; ++i) {
        for(int j = 1; j <= p2; ++j) {
            double r1 = myRand(), r2 = myRand();
            double rlen = sqrt(sq(r1) + sq(r2));
            r1 /= rlen, r2 /= rlen;
            double newX = X + r1 * step, newY = Y + r2 * step;
            double newLoss = getLoss(newX, newY);
            if(newLoss < curLoss)
                X = newX, Y = newY, curLoss = newLoss;
        }
        //printf("X=%.6f Y=%.6f loss=%.6f
", X, Y, curLoss);
        step *= 0.75;
    }
    //printf("X=%.6f Y=%.6f loss=%.6f
", X, Y, curLoss);
}

void RandomOptimize(double &X, double &Y) {
    srand(time(0));
    InnerRandomOptimize(X, Y, 10.0, 20, 2000);
    InnerRandomOptimize(X, Y, 10.0, 200, 200);
    InnerRandomOptimize(X, Y, 10.0, 2000, 20);
}
int n;
double x[105], y[105], z[105];

double dis(double X, double Y, double Z, int id) {
    double len = sqrt(sq(X - x[id]) + sq(Y - y[id]) + sq(Z - z[id]));
    return len;
}

double getLoss(double X, double Y, double Z) {
    double sumLoss = 0.0;
    for(int i = 1; i <= n; ++i)
        cmax(sumLoss, dis(X, Y, Z, i));
    return sumLoss;
}

double myRand() {
    return 2.0 * rand() / RAND_MAX - 1.0;
}

void InnerRandomOptimize(double &X, double &Y, double &Z, double step, int p1, int p2) {
    double curLoss = getLoss(X, Y, Z);
    for(int i = 1; i <= p1; ++i) {
        for(int j = 1; j <= p2; ++j) {
            double r1 = myRand(), r2 = myRand(), r3 = myRand();
            double rlen = sqrt(sq(r1) + sq(r2) + sq(r3));
            r1 /= rlen, r2 /= rlen, r3 /= rlen;
            double newX = X + r1 * step, newY = Y + r2 * step, newZ = r3 * step;
            double newLoss = getLoss(newX, newY, newZ);
            if(newLoss < curLoss)
                X = newX, Y = newY, Z = newZ, curLoss = newLoss;
        }
        //printf("X=%.6f Y=%.6f Z=%.6f loss=%.6f
", X, Y, Z, curLoss);
        step *= 0.75;
    }
    //printf("X=%.6f Y=%.6f Z=%.6f loss=%.6f
", X, Y, Z, curLoss);
}

void RandomOptimize(double &X, double &Y, double &Z) {
    srand(time(0));
    InnerRandomOptimize(X, Y, Z, 10.0, 20, 2000);
    InnerRandomOptimize(X, Y, Z, 10.0, 200, 200);
    InnerRandomOptimize(X, Y, Z, 10.0, 2000, 20);
}

启发式移动算法

原文地址:https://www.cnblogs.com/purinliang/p/14135509.html