因为是专门关于这个的博客, 所以代码就不折叠了
谁有能想到最后的最后, 真正一直恶心着我的是我把 last_pos 发挥作用之前改成了 pos, 用了一下午和一早上去手模
#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
namespace La_Pluma_math{
const double eps = 1e-10;
typedef int Point_type; // 如果点的坐标会出现小数, 把这个 int 改成 double 就可以了(int 的时候应该也不会和向量互转吧。。。不然可能出锅?)
struct Point; struct Vec; struct Line; struct Segment;
double check_0(double); // 判丢精的 0
double dis(const Point, const Point); // 点到点的距离
double dis(const Point, const Line); // 点到直线距离
double dis(const Line, const Point); // 直线到点距离
double dis(const Point, const Segment); // 点到线段距离
double dis(const Segment, const Point); // 线段到点距离
struct Point{ // 点
Point_type x, y;
Point():x(), y(){} // 默认构造函数
Point(const Vec); // 用向量初始化 (感觉非常SB)
Point(Point_type, Point_type); // 用坐标初始化
bool operator == (const Point); // 判断是否为同一个点
bool operator != (const Point); // 判断是否不为同一个点
};
struct Vec{ // 向量
double x, y;
Vec():x(), y(){} // 默认构造函数
Vec(const Point); // 用点初始化
Vec(const Segment); // 用线段初始化
Vec(double, double); // 用坐标初始化
Vec(const Point, const Point); // 用两个点初始化 (起点和终点)
Vec(double, double, double, double); // 用两个坐标初始化 (起点和终点)
Vec operator + (const Vec); // 向量加
Vec operator - (const Vec); // 向量减
double operator ^ (const Vec); // 向量叉积的模
double operator * (const Vec); // 向量点积
double operator ~ (); // 向量的模
Vec operator += (const Vec); // 以下处理一些奇怪的运算符
Vec operator -= (const Vec); // 结果发现也就这些
Vec operator - (); // 又有谁能想到减号也可以是单目运算符呢
bool operator == (const Vec); // 判断是否为共线向量
bool operator != (const Vec); // 判断是否不为共线向量
};
struct Line{ // 直线
double A, B, C;
Line():A(), B(), C(){} // 默认构造函数
Line(const Segment); // 用线段初始化
Line(double, double); // 用斜截式初始化
Line(const Point, const Point); // 用两个点初始化
Line(double, double, double, double); // 用两个坐标初始化
bool operator == (const Line); // 判断是否为同一条直线
bool operator != (const Line); // 判断是否不为同一条直线
};
struct Segment{ // 线段
Point a, b;
Segment():a(),b(){} // 默认构造函数
Segment(const Point, const Point); // 用两个端点初始化
Segment(Point_type, Point_type, Point_type, Point_type); // 用两个坐标初始化
double operator ~ (); // 线段的长度
bool operator < (Segment); // 万能的小于号
bool operator > (Segment); // 进行
bool operator <= (Segment); // 一个
bool operator >= (Segment); // 重的载
bool operator == (Segment); // 判断线段的长度是否相等
bool operator != (Segment); // 判断线段的长度是否不相等
};
Point::Point(const Vec a) { x = a.x, y = a.y; }
Point::Point(Point_type x, Point_type y) { this->x = x, this->y = y; }
bool Point::operator == (const Point a) { return x == a.x && y == a.y; }
bool Point::operator != (const Point a) { return !(*this == a); }
Vec::Vec(const Point a) { x = a.x, y = a.y; }
Vec::Vec(const Segment a) { *this = Vec(a.a, a.b); }
Vec::Vec(const Point a, const Point b) { *this = Vec(b) - Vec(a); }
Vec::Vec(double x, double y) { this->x = x, this->y = y; }
Vec Vec::operator + (const Vec b) { return Vec(x + b.x, y + b.y); }
Vec Vec::operator - (const Vec b) { return Vec(x - b.x, y - b.y); }
Vec Vec::operator - () { return Vec(-x , -y ); }
double Vec::operator ^ (const Vec b) { return x * b.y - b.x * y; }
double Vec::operator * (const Vec b) { return x * b.x + y * b.y; }
double Vec::operator ~ () { return sqrt(x * x + y * y); }
Vec Vec::operator += (const Vec b) { return *this = *this + b; }
Vec Vec::operator -= (const Vec b) { return *this = *this - b; }
bool Vec::operator == (const Vec b) { return check_0(y / b.y - x / b.x) == 0; }
bool Vec::operator != (const Vec b) { return !(*this == b); }
Line::Line(const Segment a) { *this = Line(a.a, a.b); }
Line::Line(double k, double b) { A = k, B = 0, C = b; }
Line::Line(double a, double b, double c, double d) { *this = Line(Point(a, b), Point(c, d)); }
Line::Line(const Point a, const Point b){
if(a.x == b.x) A = 1, B = 0, C = -a.x;
else if(a.y == b.y) A = 0, B = 1, C = -a.y;
else A = (double)(a.y - b.y) / (a.x - b.x), B = -1, C = (double)(a.x * b.y - b.x * a.y) / (a.x - b.x);
}
bool Line::operator == (const Line a) { return check_0(A * a.B - B * a.A) == 0 && check_0(A * a.C - C * a.A) == 0 && check_0(B * a.C - C * a.B) == 0; }
bool Line::operator != (const Line a) { return !(*this == a); }
Segment::Segment(const Point a, const Point b) { this->a = a, this->b = b; }
Segment::Segment(Point_type a, Point_type b, Point_type c, Point_type d) { *this = Segment(Point(a, b), Point(c, d)); }// 因为一些显然的问题, 这里就不对齐了
double Segment::operator ~ () { return dis(a, b); }
bool Segment::operator < (Segment a) { return (~(*this)) < (~a); }
bool Segment::operator > (Segment a) { return a < *this; }
bool Segment::operator <= (Segment a) { return !(*this > a); }
bool Segment::operator >= (Segment a) { return !(*this < a); }
bool Segment::operator == (Segment a) { return !(*this < a) && !(*this > a); }
bool Segment::operator != (Segment a) { return (*this < a) || (*this > a); }
double check_0(double a){ return fabs(a) < eps ? 0 : a; }
double dis(const Point pos1, const Point pos2) { return check_0(sqrt((pos1.x - pos2.x) * (pos1.x - pos2.x) + (pos1.y - pos2.y) * (pos1.y - pos2.y))); }
double dis(const Line link, const Point pos) { return check_0(fabs(link.A * pos.x + link.B * pos.y + link.C) / sqrt(link.A * link.A + link.B * link.B)); }
double dis(const Point pos, const Line link) { return dis(link, pos); }
double dis(const Point pos, const Segment Seg) { return dis(Seg, pos); }
double dis(const Segment Seg, const Point pos) {
Vec vector1(Seg.a, pos);
Vec vector2(Seg.b, pos);
Vec vector3 = Seg;
if(check_0(vector1 * vector3) < 0) return ~vector1;
if(check_0(vector2 * vector3) > 0) return ~vector2;
return check_0(fabs((vector1 ^ vector3) / (~vector3)));
}
} using namespace La_Pluma_math;
int n, m, id_cnt, end_tim, now_tim;
int sum_of_tower, agg_of_tower, r_of_tower;
int map[10][10], vis[10][10];
const int yy[] = {1, 0, -1, 0}, xx[] = {0, 1, 0, -1};
const int xy[4][4] = {
{3, 2, 1, 0},// 东
{0, 3, 2, 1},// 南
{1, 0, 3, 2},// 西
{2, 1, 0, 3} // 北
};
Point tower[22];
struct antbuster{
int years, HP, Lv;
Point last_pos, pos;
bool target;
};
typedef std::vector<antbuster>::iterator vec_it;
double init_HP(const antbuster &a){ return pow(1.1, a.Lv) * 4; }
std::vector<antbuster> ant;
void get_new_ant(){
++id_cnt;
antbuster tmp;
tmp.Lv = ceil((double)id_cnt / 6);
tmp.HP = init_HP(tmp);
tmp.years = 0;
tmp.target = false;
tmp.pos = Point(0, 0);
tmp.last_pos = Point(0, 0);
vis[0][0] = true;
ant.push_back(tmp);
}
bool check_mov(vec_it a, int i){
return a->pos.x + xx[i] > n || a->pos.x + xx[i] < 0 ||
a->pos.y + yy[i] > m || a->pos.y + yy[i] < 0 ||
vis[a->pos.x + xx[i]][a->pos.y + yy[i]] ||
(a->last_pos.x - a->pos.x == xx[i] && a->last_pos.y - a->pos.y == yy[i]);
}
vec_it find_target(){
if(ant.empty()) return ant.end();
for(vec_it i = ant.begin(); i != ant.end(); ++i) if(i->target) return i;
return ant.end();
}
void mov(vec_it a){
int flag1[4] = {1, 1, 1, 1}, flag2[4] = {1, 1, 1, 1}, tmp = 0;
#define choice ((flag1[0] & flag2[0]) + (flag1[1] & flag2[1]) + (flag1[2] & flag2[2]) + (flag1[3] & flag2[3]))
for(int i = 0; i < 4; ++i) if(check_mov(a, i)) flag1[i] = 0;
for(int i = 0; i < 4; ++i) if(flag1[i]) tmp = std::max(tmp, map[a->pos.x + xx[i]][a->pos.y + yy[i]]);
for(int i = 0; i < 4; ++i) if(map[a->pos.x + xx[i]][a->pos.y + yy[i]] < tmp) flag2[i] = 0;
if(choice == 0){
a->last_pos = a->pos;
return;
}
tmp = 0;
while(!(flag1[tmp] && flag2[tmp])) ++tmp;
if(a->years && a->years % 5 == 4)
for(int i = 0; i < 4; ++i)
if(!check_mov(a, xy[tmp][i])){
tmp = xy[tmp][i];
break;
}
vis[a->pos.x][a->pos.y] = false;
a->last_pos = a->pos;
a->pos.x += xx[tmp], a->pos.y += yy[tmp];
vis[a->pos.x][a->pos.y] = true;
}
void fire(Point a){
double min_dis = 1e18; vec_it aim = ant.end();
for(vec_it i = ant.begin(); i != ant.end(); ++i){
double now_dis = dis(a, i->pos);
if(now_dis <= r_of_tower && now_dis < min_dis) min_dis = now_dis, aim = i;
}
if(aim != ant.end()) aim->HP -= agg_of_tower;
}
void fire(Point a, vec_it it){
if(dis(a, it->pos) <= r_of_tower){
Segment light(a, it->pos);
for(vec_it i = ant.begin(); i != ant.end(); ++i) if(dis(light, i->pos) <= 0.5) i->HP -= agg_of_tower;
}else fire(a);
}
void print(){
printf("%ld\n", ant.size());
for(auto i : ant) printf("%d %d %d %d %d\n", i.years, i.Lv, i.HP, i.pos.x, i.pos.y);
}
void start_game(){
for(now_tim = 1; now_tim <= end_tim; ++now_tim){
if(ant.size() < 6 && !vis[0][0]) get_new_ant();
for(auto i : ant) map[i.pos.x][i.pos.y] += i.target ? 5 : 2;
for(vec_it i = ant.begin(); i != ant.end(); ++i) mov(i);
for(vec_it i = ant.begin(); i != ant.end(); ++i){
if(find_target() == ant.end() && i->pos == Point(n, m)){
i->HP = std::min(init_HP(*i), i->HP + init_HP(*i) / 2);
i->target = true;
}
}
vec_it target = find_target();
if(target != ant.end()) for(int i = 1; i <= sum_of_tower; ++i) fire(tower[i], target);
else for(int i = 1; i <= sum_of_tower; ++i) fire(tower[i]);
bool upd = true;
while(upd){
upd = false;
for(vec_it i = ant.begin(); i != ant.end(); ++i) if(i->HP < 0){
vis[i->pos.x][i->pos.y] = false;
ant.erase(i);
upd = true;
break;
}
}
target = find_target();
if(target != ant.end() && target->pos == Point(0, 0)){ printf("Game over after %d seconds\n", now_tim); break; }
for(int i = 0; i <= n; ++i) for(int j = 0; j <= m; ++j) if(map[i][j]) --map[i][j];
for(vec_it i = ant.begin(); i != ant.end(); ++i) ++i->years;
}
if(now_tim > end_tim) printf("The game is going on\n");
print();
}
int main(){
scanf("%d%d%d%d%d", &n, &m, &sum_of_tower, &agg_of_tower, &r_of_tower);
for(int i = 1; i <= sum_of_tower; ++i){
int x, y;
scanf("%d%d", &x, &y);
vis[x][y] = true;
tower[i] = Point(x, y);
}
scanf("%d", &end_tim);
start_game();
return 0;
}