【LOJ】#2076. 「JSOI2016」炸弹攻击

题解

我冷静一下,话说如果去掉建筑和R的限制好像是模拟退火吧

然后开始写模拟退火了,起始点就随机一个敌人作为起始点
没对着数据写了一下获得了70pts,感到美滋滋

然后对着数据卡了很久……发现有个数据点似乎需要从初始温度小一点的情况开始跳,于是就10次从20000降温,10次从2000降温
AC啦

该题的AC率显著地下降了= =

代码

#include <bits/stdc++.h>
#define enter putchar('
')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define MAXN 100005
#define mo 99994711
#define pb push_back
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
int dx[] = {0,-1,0,1};
int dy[] = {1,0,-1,0};
struct Point {
    db x,y;
    Point() {}
    Point(db _x,db _y) {x = _x;y = _y;}
    friend Point operator + (const Point &a,const Point &b) {return Point(a.x + b.x,a.y + b.y);}
    friend Point operator - (const Point &a,const Point &b) {return Point(a.x - b.x,a.y - b.y);}
    friend Point operator * (const Point &a,const db &d) {return Point(a.x * d,a.y * d);}
    friend Point operator / (const Point &a,const db &d) {return Point(a.x / d,a.y / d);}
    friend db operator * (const Point &a,const Point &b) {return a.x * b.y - a.y * b.x;}
    friend db dot(const Point &a,const Point &b) {return a.x * b.x + a.y * b.y;}
    db norm() {return sqrt(x * x + y * y);}
}Enemy[1005];
struct circle {
    Point O;db r;
}C[15];
u32 Rand() {
    static u32 x = 20020421;
    return x += x << 2 | 1;
}
db Rand_range() {
    return (db)(Rand() % 10000) / 10000.0;
}
int N,M,ans;
db R;
void Init() {
    read(N);read(M);scanf("%lf",&R);
    db x,y,r;
    for(int i = 1 ; i <= N ; ++i) {
        scanf("%lf%lf%lf",&x,&y,&r);
        C[i].O = Point(x,y);C[i].r = r;
    }
    for(int i = 1 ; i <= M ; ++i) {
        scanf("%lf%lf",&x,&y);
        Enemy[i] = Point(x,y);
    }
}
int Count(Point x) {
    db r = R;
    for(int i = 1 ; i <= N ; ++i) {
        r = min(r,(C[i].O - x).norm() - C[i].r);
    }
    int cnt = 0;
    for(int i  = 1 ; i <= M ; ++i) {
        if((Enemy[i] - x).norm() <= r + eps) ++cnt;
    }
    return cnt;
}
void Solve(int num) {
    db T = num,delta = 0.99;
    Point x = Enemy[Rand() % M + 1];
    int tmp = 0;
    while(T > 0.01) {
        Point t;tmp = 0;
        for(int i = 0 ; i <= 3 ; ++i) {
            Point k = x + Point(T * dx[i],T * dy[i]);
            int a = Count(k);
            if(a > tmp) {t = k;tmp = a;}
        }
        if(tmp > ans) {x = t;ans = tmp;}
        else if(exp((ans - tmp) * 0.1 / T) > Rand_range()) x = t;
        T *= delta;
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    ans = 1;
    int cnt = 10;
    while(cnt--) Solve(20000);
    cnt = 10;
    while(cnt--) Solve(2000);
    out(ans);enter;
    return 0;
}
原文地址:https://www.cnblogs.com/ivorysi/p/9543716.html