P5544 [JSOI2016]炸弹攻击1 题解
\(Solution\)
我们考虑模拟退火。
我们随机一个点作为炸弹炸的地方,至于炸弹的半径,贪心的想肯定是越大越好啊,所以我们先根据建筑物来找炸弹的半径。
然后再来计算这个炸弹能炸死的敌人数目即可。
然后就是愉快的调参数环节。
/*
Work by: TLE_Automation
*/
#include<ctime>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define int long long
using namespace std;
const int N = 1e6 + 10;
const double lim = 1e-10;
const double down = 0.9996;
const int MAXN = 2e5 + 10;
inline char readchar() {
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
int res = 0, f = 0;
char ch = readchar();
for (; !isdigit(ch); ch = readchar()) if (ch == '-') f = 1;
for (; isdigit(ch); ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
return f ? -res : res;
}
inline void print(int x) {
if (x < 0 ) putchar('-'), x = -x;
if (x > 9 ) print(x / 10);
putchar(x % 10 + '0');
}
int n, m, R, maxans, delans, nowans;
double nowx, nowy, limx, limy, ansx, ansy;
struct _Node {
int x, y, r;
}a[20], p[MAXN];
double dis(double sx, double sy, double ex, double ey) {
return sqrt((ex - sx) * (ex - sx) + (ey - sy) * (ey - sy));
}
int Calc(double x, double y) {
double MaxR = R * 1.0;
for(int i = 1; i <= n; i++) {
double Dis = dis(x, y, a[i].x, a[i].y);
MaxR = min(MaxR, (double)Dis - a[i].r);
}
int Sum = 0;
for(int i = 1; i <= m; i++) {
if(dis(x, y, p[i].x, p[i].y) <= MaxR) Sum++;
}
return Sum;
}
void SA() {
double T = 2022;
while(T >= lim) {
nowx = limx + ((rand() << 1) - RAND_MAX) * T;
nowy = limy + ((rand() << 1) - RAND_MAX) * T;
nowans = Calc(nowx, nowy);
delans = nowans - maxans;
if(delans > 0) maxans = nowans, limx = ansx = nowx, limy = ansy = nowy;
T *= down;
}
}
signed main()
{
srand(time(NULL));
n = read(), m = read(), R = read();
for(int i = 1; i <= n; i++) a[i].x = read(), a[i].y = read(), a[i].r = read();
for(int i = 1; i <= m; i++) p[i].x = read(), p[i].y = read();
nowans = Calc(nowx, nowy);
for(int i = 1; i <= 3; i++) SA();
printf("%lld\n", nowans);
return 0;
}