[JSOI2016] 炸弹攻击1

题目传送门

模拟退火大法6

解法

模拟退火
随机圆心的位置即可
调参路漫漫

Code

#include 
#include 
#include 

#define rep(i, j, k) for (register int i = j; i <= k; i++)
#define _rep(i, j, k) for (register int i = k; i >= j; i--)
#define _b_pct __builtin_popcount

using ll = long long;
using db = double;
using namespace std;

const int N = 2e4+ 7, M = 2e6+7, K = 16, INF = 1e9;
const ll inv2 = 499122177, LLF = 1e16, mod = 1e9+7;
const db eps=1e-6;

int n,m,ans;
db X,Y,R;
struct Pos {
    db x,y,r;
}p[N],em[N];

ll qpow(ll ba, ll pow) {
    ll res = 1;
    while (pow) {
        if (pow & 1)
            res = res * ba % mod;
        ba = ba * ba % mod, pow >>= 1;
    }
    return res;
}

ll Add(ll x, ll y) { return ((x + y) % mod); }

ll Mul(ll x, ll y) { return ((x * y) % mod); }

ll Del(ll x, ll y) { return (x - y < 0 ? x - y + mod : x - y); }

ll Inv(ll x) { return qpow(x, mod - 2); }

ll Block(ll x) {
    ll res = 0;
    for (ll l = 1, r; l <= x; l = r + 1) {
        r = x / (x / l);
        res = Add(res, Mul((x / l), (r - l + 1)));
    }
    return res;
}

db Rand() { return (db)rand()/RAND_MAX; }

db solve(db xx,db yy) {
    int tmp=0; db len=INF;
    rep(i,1,n) {
        db tx=p[i].x-xx,ty=p[i].y-yy;
        len=fmin(len,sqrt(tx*tx+ty*ty)-p[i].r);
    }
    len=fmin(len,R);
    if(len<0) tmp=0;
    else {
        rep(i,1,m) {
            db tx=em[i].x-xx,ty=em[i].y-yy;
            if(len>=sqrt(tx*tx+ty*ty)) tmp++;
        }
    }
    if(tmp>ans) ans=tmp,X=xx,Y=yy;
    return tmp;
}

void SA() {
    db t=300076;
    db nx=X,ny=Y;
    while(t>0.000150) {
        db tx=nx+t*(Rand()*2-1),ty=ny+t*(Rand()*2-1);
        db delta=solve(tx,ty)-solve(nx,ny);
        if(exp(-delta/t)

你可能感兴趣的:(算法,模拟退火算法)