题目链接
模拟就行了,比赛的时候一直一直一直一直不过,WA哭了(OAO)
大概思路,
h
p
hp
hp对虫子而言就是表示剩余的
h
p
hp
hp,对狂热者而言就是表示是否离场。
每有一只虫子进来,标识它是个虫子,记录
h
p
hp
hp。每有一个狂热者加入,标识他是狂热者,记
h
p
>
0
hp>0
hp>0(等于1、2、3…都行),然后遍历已有的虫子,找到最近的一个,然后以该虫子的位置为新位置,以狂热者的攻击范围为半径,扫描在当前攻击范围内的虫子,并使其
h
p
−
=
3
×
a
t
k
hp-=3\times atk
hp−=3×atk,判断攻击范围内是否有虫子存活,如果有,令狂热者
h
p
<
0
hp<0
hp<0(等于-1、-2…都行)
最后判断, h p > 0 hp>0 hp>0说明虫子没死或者狂热者没有离场,输出Yes,否则输出No
注意使用 long long
注意计算欧几里得距离时,开根号会有精度误差,尽量避免
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
const int N = 2e3 + 10;
//#define LOCAL
int n;
typedef long long ll;
struct point{
ll x, y;
point(){}
point(ll x, ll y){
this->x = x;
this->y = y;
}
};
struct c{
ll hp;
point pt;
bool is_person;
c(){
this->hp = 0;
}
c(ll hp, ll x, ll y){
this->hp = hp;
// this->pt = point(x, y);
this->pt = {x, y};
}
};
ll gcd_dist(point a, point b){
ll ch1 = a.x - b.x;
ll ch2 = a.y - b.y;
return ch1 * ch1 + ch2 * ch2;
}
c life[N];
int ind;
int main(){
#ifdef LOCAL
freopen("in", "r", stdin);
freopen("out", "w", stdout);
#endif
cin >> n;
ind = 0;
for (int i = 1; i <= n; i++){
int f;
scanf("%d", &f);
if (f == 1){
ll x, y, h;
scanf("%lld %lld %lld", &x, &y, &h);
life[++ind] = c(h, x, y);
life[ind].is_person = false;
}
else {
ll x, y, atk, r;
scanf("%lld %lld %lld %lld", &x, &y, &atk, &r);
life[++ind] = c(1, x, y);
life[ind].is_person = true;
int k = -1;
ll mn = (ll)1e18;
point t_pt = point(x, y);
for (int j = 1; j < ind; j++){
if (!life[j].is_person && life[j].hp > 0){
if (mn > gcd_dist(life[j].pt, t_pt)){
mn = gcd_dist(life[j].pt, t_pt);
k = j;
}
}
}
if (k != -1){
t_pt = life[k].pt;
for (int j = 1; j < ind; j++){
if (!life[j].is_person && life[j].hp > 0 && gcd_dist(t_pt, life[j].pt) <= r * r){
life[j].hp -= atk * 3;
if (life[j].hp > 0)life[ind].hp = -1;
}
}
}
}
}
for (int i = 1; i <= ind; i++){
if (life[i].hp > 0)puts("Yes");
else puts("No");
}
return 0;
}