CCPC 2020 我得重新集结部队

这是一个关于编程竞赛的题目,主要涉及数据结构和算法的应用。题目描述了一个模拟场景,其中虫子和狂热者交互,狂热者根据其攻击范围对虫子造成伤害。关键在于计算欧几里得距离并更新虫子的健康值。如果虫子在攻击范围内存活或狂热者未离场,则输出'Yes',否则输出'No'。代码中使用了long long类型以避免精度问题,并且注意到了根号计算可能引入的误差。
摘要由CSDN通过智能技术生成

题目链接
模拟就行了,比赛的时候一直一直一直一直不过,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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值