Loading

2018 ICPC 南京 D Country Meow(模拟退火|三分)

2018 ACM-ICPC 南京 D Country Meow

传送门

题意:

裸的最小球覆盖的半径

解题思路:

往距离当前点最远点跳的模拟退火,又好想又方便,同样一份代码但是poj2069死活过不去,一开始以为就我这样..后来到网上查了下这题的代码,改一改往poj一贴,全都wa了...没一个能活的...总感觉应该是poj2069的数据有点离谱,大概不是我的问题吧...大概
又写了下三分的写法

代码

#include <bits/stdc++.h>
using namespace std;
// freopen("k.in", "r", stdin);
// freopen("k.out", "w", stdout);
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 2e5 + 7;
const ll MAXM = 4e5 + 7;
const int MOD = 1e9 + 7;
const double eps = 1e-7;
struct Point
{
    double x, y, z;
} P[MAXN];
double dis(Point a, Point b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z));
}
int n;
double ans = INF;
double solve()
{
    double Statr_T = 1000000;
    double t = Statr_T;
    double rate = 0.99;
    Point now = {0, 0, 0};
    int mxgo = 0;
    double mxlen = dis(now, P[mxgo]);
    while (t > eps)
    {
        double pre = dis(now, P[mxgo]);
        for (int i = 0; i < n; i++)
        {
            if (dis(now, P[i]) > dis(now, P[mxgo]))
                mxgo = i;
        }
        double nxtx = now.x + (P[mxgo].x - now.x) * t * rand() / RAND_MAX / Statr_T;
        double nxty = now.y + (P[mxgo].y - now.y) * t * rand() / RAND_MAX / Statr_T;
        double nxtz = now.z + (P[mxgo].z - now.z) * t * rand() / RAND_MAX / Statr_T;
        double maxx = 0;
        Point nxt = {nxtx, nxty, nxtz};
        for (int i = 0; i < n; i++)
            maxx = max(maxx, dis(P[i], nxt));
        double delta = pre - maxx;
        if (delta < 0)
            now = nxt;
        else if (exp(delta / t) > 1.0 * rand() / RAND_MAX)
            now = nxt;
        ans = min(ans, maxx);
        t *= rate;
    }
    return ans;
}
int main()
{
    srand(time(NULL));
    while (~scanf("%d", &n) && n)
    {
        ans = INF;
        for (int i = 0; i < n; i++)
            scanf("%lf%lf%lf", &P[i].x, &P[i].y, &P[i].z);
        for (int i = 1; i <= 10; i++)
            solve();
        printf("%.8f\n", ans);
    }
    return 0;
}

三分版

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
// freopen("k.in", "r", stdin);
// freopen("k.out", "w", stdout);
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
mt19937 rnd(time(NULL));
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 | 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<char, char> PCC;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 2e5 + 7;
const ll MAXM = 4e5 + 7;
const int MOD = 1e9 + 7;
const double eps = 1e-8;
struct Point
{
    double x, y, z;
} P[MAXN];
int n;
double ans = INF;
double dis(Point a, Point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z)); }
double check(Point x)
{
    double ret = 0;
    for (int i = 1; i <= n; i++)
        ret = max(ret, dis(P[i], x));
    return ret;
}
Point solve(Point now, int op) //x-1,y-2,z-3
{
    double l = -100000, r = 100000;
    Point nodel = now, noder = now;
    while (r - l > eps)
    {
        double mid1 = l + (r - l) / 3;
        double mid2 = r - (r - l) / 3;
        if (op == 1)
            nodel.x = mid1, noder.x = mid2;
        else if (op == 2)
            nodel.y = mid1, noder.y = mid2;
        else
            nodel.z = mid1, noder.z = mid2;
        if (op != 3)
        {
            nodel = solve(nodel, op + 1);
            noder = solve(noder, op + 1);
        }
        if (check(nodel) > check(noder))
            l = mid1;
        else
            r = mid2;
    }
    return noder;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lf%lf%lf", &P[i].x, &P[i].y, &P[i].z);
    Point now = {0, 0, 0};
    now = solve(now, 1);
    printf("%.10f\n", check(now));
    return 0;
}
posted @ 2020-12-04 19:35  GrayKido  阅读(188)  评论(0编辑  收藏  举报