bzoj1033: [ZJOI2008]杀蚂蚁antbuster

刚开博客,放几道大模拟

杀蚂蚁

www.lydsy.com/JudgeOnline/problem.php?id=1033

#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXN 10
#define MAXM 10
#define EPS (1e-8)

struct Point
{
    int x, y;
    Point(int _x = 0, int _y = 0)
        : x(_x), y(_y) {}
    bool operator== (const Point &a)const
    {
        return x == a.x && y == a.y;
    }
    bool operator!= (const Point &a)const
    {
        return x != a.x || y != a.y;
    }
};
double dis(const Point &a, const Point &b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
struct Ant
{
    Point pos, last;
    long age, k, blood, life, active;
    bool cake;
    Ant(Point _pos, Point _last, long _age, long _k, long _blood, long _life, long _active, bool _cake)
        : pos(_pos), last(_last), age(_age), k(_k), blood(_blood), life(_life), active(_active), cake(_cake) {}
    bool operator< (const Ant &x)const
    {
        return age > x.age;
    }
};

int n, m, d, r;
long T;
vector<Point> turret;
vector<Ant> ant;
long antct;
long info[MAXN][MAXN];
int hasant[MAXN][MAXN];
bool hasturret[MAXN][MAXN];
bool hascake;

void Init()
{
    hascake = true;
    antct = 0;
    memset(info, 0, sizeof(info));
    memset(hasant, 0, sizeof(hasant));
    memset(hasturret, 0, sizeof(hasturret));
    scanf("%d%d", &n, &m);
    int s;
    scanf("%d%d%d", &s, &d, &r);
    while (s--)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        turret.push_back(Point(x, y));
        hasturret[x][y] = true;
    }
    scanf("%ld", &T);
}
void NewAnt()
{
    if (ant.size() < 6 && !hasant[0][0])
    {
        long k = antct++ / 6 + 1;
        long blood = 4 * pow(1.1, k);
        ant.push_back(Ant(Point(0, 0), Point(0, 0), 0, k, blood, blood, 0, false));
        ++hasant[0][0];
    }
}
void CreatInfo()
{
    for (vector<Ant>::iterator i = ant.begin(); i != ant.end(); ++i)
        info[i->pos.x][i->pos.y] += (i->cake ? 5 : 2);
}
bool check(int x, int y)
{
    return x >= 0 && y >= 0 && x <= n && y <= m && !hasant[x][y] && !hasturret[x][y];
}
int g[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
void MoveOne(vector<Ant>::iterator x)
{
    ++x->active;
    vector<int> cango;
    for (int i = 0; i < 4; ++i)
        if (check(x->pos.x + g[i][0], x->pos.y + g[i][1]) && Point(x->pos.x + g[i][0], x->pos.y + g[i][1]) != x->last)
            cango.push_back(i);
    if (cango.size() == 0)
    {
        x->last = x->pos;
        return;
    }
    long maxinfo = 0;
    for (vector<int>::iterator i = cango.begin(); i != cango.end(); ++i)
        maxinfo = max(maxinfo, info[x->pos.x + g[*i][0]][x->pos.y + g[*i][1]]);
    for (vector<int>::iterator i = cango.begin(); i != cango.end();)
        if (maxinfo == info[x->pos.x + g[*i][0]][x->pos.y + g[*i][1]])
            ++i;
        else
            i = cango.erase(i);
    Point t;
    if (x->active % 5)
        t = Point(x->pos.x + g[cango[0]][0], x->pos.y + g[cango[0]][1]);
    else
        for (int i = 1; i <= 4; ++i)
            if (check(x->pos.x + g[(cango[0] - i + 4) % 4][0], x->pos.y + g[(cango[0] - i + 4) % 4][1])
                && x->last != Point(x->pos.x + g[(cango[0] - i + 4) % 4][0], x->pos.y + g[(cango[0] - i + 4) % 4][1]))
            {
                t = Point(x->pos.x + g[(cango[0] - i + 4) % 4][0], x->pos.y + g[(cango[0] - i + 4) % 4][1]);
                break;
            }
    x->last = x->pos;
    x->pos = t;
}
void AntMove()
{
    for (vector<Ant>::iterator i = ant.begin(); i != ant.end(); ++i)
    {
        --hasant[i->pos.x][i->pos.y];
        MoveOne(i);
        ++hasant[i->pos.x][i->pos.y];
        if (i->pos.x == n && i->pos.y == m && hascake)
        {
            i->blood += i->life / 2;
            if (i->blood > i->life)
                i->blood = i->life;
            hascake = false;
            i->cake = true;
        }
    }
}
typedef Point Vector;
Vector operator- (const Point &a, const Point &b)
{
    return Vector(a.x - b.x, a.y - b.y);
}
struct Line
{
    Point p;
    Vector v;
    Line(const Point &a, const Point &b)
        : p(a), v(b - a) {}
};
int dcmp(double a)
{
    if (fabs(a) <= EPS)
        return 0;
    return a > 0 ? 1 : -1;
}
int GetCut(const Line &L, const Point &C, double &t1, double &t2)
{
    double a = L.v.x, b = L.p.x - C.x, c = L.v.y, d = L.p.y - C.y;
    double e = a * a + c * c, f = 2 * (a * b + c * d), g = b * b + d * d - 0.25;
    double delta = f * f - 4 * e * g;
    if (dcmp(delta) < 0)
        return 0;
    if (dcmp(delta) == 0)
    {
        t1 = t2 = -f / (2 * e);
        return 1;
    }
    t1 = (-f - sqrt(delta)) / (2 * e);
    t2 = (-f + sqrt(delta)) / (2 * e);
    return 2;
}
bool CanAttack(const Point &a, const Point &b, const Point &c)
{
    double t1, t2;
    int k = GetCut(Line(a, b), c, t1, t2);
    if (k == 0)
        return false;
    if (k == 1)
        return dcmp(t1) >= 0 && dcmp(t1 - 1) <= 0;
    else
        return (dcmp(t1) >= 0 && dcmp(t1 - 1) <= 0) || (dcmp(t2) >= 0 && dcmp(t2 - 1) <= 0);
}
void TurretAct()
{
    for (vector<Point>::iterator i = turret.begin(); i != turret.end(); ++i)
    {
        Point p(-1, -1);
        double dp;
        for (vector<Ant>::iterator j = ant.begin(); j != ant.end(); ++j)
        {
            double d = dis(*i, j->pos);
            if (d <= r)
                if (p.x == -1 || j->cake || dcmp(d - dp) < 0)
                {
                    p = j->pos;
                    dp = d;
                    if (j->cake)
                        break;
                }
        }
        if (p.x != -1)
            for (vector<Ant>::iterator j = ant.begin(); j != ant.end();++j)
                if (CanAttack(*i, p, j->pos))
                    j->blood -= d;
    }
    for (vector<Ant>::iterator i = ant.begin(); i != ant.end();)
        if (i->blood < 0)
        {
            --hasant[i->pos.x][i->pos.y];
            if (i->cake)
                hascake = true;
            i = ant.erase(i);
        }
        else
            ++i;
}
bool AntWin()
{
    if (hascake)
        return false;
    for (vector<Ant>::iterator i = ant.begin(); i != ant.end(); ++i)
        if (i->cake && i->pos.x == 0 && i->pos.y == 0)
            return true;
    return false;
}
void ShowAnt()
{
    printf("%d\n", ant.size());
    sort(ant.begin(), ant.end());
    for (vector<Ant>::iterator i = ant.begin(); i != ant.end(); ++i)
        printf("%ld %ld %ld %d %d\n", i->age, i->k, i->blood, i->pos.x, i->pos.y);
}
void DecreaseInfo()
{
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= m; ++j)
            if (info[i][j])
                --info[i][j];
}
void AntGrow()
{
    for (vector<Ant>::iterator i = ant.begin(); i != ant.end(); ++i)
        ++i->age;
}
int main()
{
    Init();
    for (long i = 1; i <= T; ++i)
    {
        NewAnt();
        CreatInfo();
        AntMove();
        TurretAct();
        if (AntWin())
        {
            printf("Game over after %ld seconds\n", i);
            ShowAnt();
            return 0;
        }
        DecreaseInfo();
        AntGrow();
    }
    printf("The game is going on\n");
    ShowAnt();
    return 0;
}


阅读更多

没有更多推荐了,返回首页