模拟退火学习笔记

[SCOI2010]传送带

方法1:三分套三分

踩坑:第一层三分结束的时候直接返回的solve()函数,这样当第二条传送带长度为0时不会进入第二个三分。所以应该返回tri2()函数。

#include <iostream>
#include <cmath>

using namespace std;

const double eps = 1e-3;
double Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, P, Q, R;
double X1, Y1, X2, Y2;

double dis(double x1, double y1, double x2, double y2) {
    return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
double f1(double a1, double a2) {
    return a1 + (a2 - a1) / 3;
}
double f2(double a1, double a2) {
    return a2 - (a2 - a1) / 3;
}

double solve() {
    return dis(Ax, Ay, X1, Y1) / P + dis(X1, Y1, X2, Y2) / R + dis(Dx, Dy, X2, Y2) / Q;
}

double tri2(double x1, double y1, double x2, double y2) {
    if (dis(x1, y1, x2, y2) < eps) {
        X2 = max(x1, x2), Y2 = max(y1, y2);
        return solve();
    }
    double mx1 = f1(x1, x2), mx2 = f2(x1, x2), my1 = f1(y1, y2), my2 = f2(y1, y2);
    X2 = mx1, Y2 = my1;
    double temp_m1 = solve();
    X2 = mx2, Y2 = my2;
    double temp_m2 = solve();
    if (temp_m1 < temp_m2) {
        return tri2(x1, y1, mx2, my2);
    }
    else {
        return tri2(mx1, my1, x2, y2);
    }
    return -1;
}

double tri1(double x1, double y1, double x2, double y2) {
    if (dis(x1, y1, x2, y2) < eps) {
        X1 = max(x1, x2), Y1 = max(y1, y2);
        return tri2(Cx, Cy, Dx, Dy);
    }
    double mx1 = f1(x1, x2), mx2 = f2(x1, x2), my1 = f1(y1, y2), my2 = f2(y1, y2);
    X1 = mx1, Y1 = my1;
    double temp_m1 = tri2(Cx, Cy, Dx, Dy);
    X1 = mx2, Y1 = my2;
    double temp_m2 = tri2(Cx, Cy, Dx, Dy);
    if (temp_m1 < temp_m2) {
        return tri1(x1, y1, mx2, my2);
    }
    else {
        return tri1(mx1, my1, x2, y2);
    }
    return -1;
}

signed main() {
    cin >> Ax >> Ay >> Bx >> By >> Cx >> Cy >> Dx >> Dy >> P >> Q >> R;
    printf("%.2lf\n", tri1(Ax, Ay, Bx, By));
    return 0;
}
posted @ 2025-05-01 16:36  hcx1999  阅读(18)  评论(0)    收藏  举报