2023.4.5 魔兽世界(三)开战
卡着时间没测,应该没大问题
#include <bits/stdc++.h>
using namespace std;
int current_time = -5;
map<char*, int> m;
void print_time() {
printf("%03d:%02d ", current_time / 60, current_time % 60);
}
int game_over;
class Weapon {
public:
int type, unbreaking;
const char *get_name() { return type == 0 ? "sword" : type == 1 ? "bomb" : "arrow"; }
Weapon(int x = 0) : type(x), unbreaking(x == 2 ? 2 : x == 1 ? 1 : 2147483647) { }
};
class Warrior {
const static int _kind = -1;
public:
const static int _attack = 0;
vector<Weapon *> w;
int health, id;
const static int init_health = 0;
Warrior(int id, int health) : id(id), health(health) { }
virtual int get_init_health() { return init_health; }
virtual int generate(int id, int n, float m) { }
virtual int generate(int id, int n) { }
virtual int generate(int id) { }
virtual int kind() = 0;
virtual int attack() = 0;
virtual void show() { }
virtual void one_step() { }
virtual ~Warrior() {
for (auto x : w) delete x;
}
};
class WarriorDragon : public Warrior {
const static int _kind = 0;
public:
float morale;
static int init_health, _attack;
WarriorDragon(int id, float m) : Warrior(id, init_health), morale(m) {
w.emplace_back(new Weapon(id % 3));
}
virtual void set_init_health(int x) { init_health = x; }
virtual int get_init_health() { return init_health; }
virtual int kind() { return _kind; }
virtual int attack() { return _attack; }
};
class WarriorNinja : public Warrior {
const static int _kind = 1;
public:
static int init_health, _attack;
WarriorNinja(int id) : Warrior(id, init_health) {
w.emplace_back(new Weapon(id % 3));
w.emplace_back(new Weapon((id + 1) % 3));
}
virtual void set_init_health(int x) { init_health = x; }
virtual int get_init_health() { return init_health; }
virtual int kind() { return _kind; }
virtual int attack() { return _attack; }
};
class WarriorIceman : public Warrior {
const static int _kind = 2;
public:
static int init_health, _attack;
WarriorIceman(int id) : Warrior(id, init_health) {
w.emplace_back(new Weapon(id % 3));
}
virtual void set_init_health(int x) { init_health = x; }
virtual int get_init_health() { return init_health; }
virtual void one_step() {
health -= health / 10;
}
virtual int kind() { return _kind; }
virtual int attack() { return _attack; }
};
class WarriorLion : public Warrior {
const static int _kind = 3;
public:
int loyalty;
static int init_health, _attack, k;
WarriorLion(int id, int l) : Warrior(id, init_health), loyalty(l) {
w.emplace_back(new Weapon(id % 3));
}
virtual void set_init_health(int x) { init_health = x; }
virtual int get_init_health() { return init_health; }
virtual void one_step() {
loyalty -= k;
}
virtual int kind() { return _kind; }
virtual int attack() { return _attack; }
};
class WarriorWolf : public Warrior {
const static int _kind = 4;
public:
static int init_health, _attack;
WarriorWolf(int id) : Warrior(id, init_health) { }
virtual void set_init_health(int x) { init_health = x; }
virtual int get_init_health() { return init_health; }
virtual void show() { }
virtual int kind() { return _kind; }
virtual int attack() { return _attack; }
};
WarriorDragon dragon_obj(0, 0);
int WarriorDragon::init_health = 0, WarriorDragon::_attack = 0;
WarriorNinja ninja_obj(0);
int WarriorNinja::init_health = 0, WarriorNinja::_attack = 0;
WarriorIceman iceman_obj(0);
int WarriorIceman::init_health = 0, WarriorIceman::_attack = 0;
WarriorLion lion_obj(0, 0);
int WarriorLion::init_health = 0, WarriorLion::_attack = 0, WarriorLion::k = 0;
WarriorWolf wolf_obj(0);
int WarriorWolf::init_health = 0, WarriorWolf::_attack = 0;
const char *getname(Warrior *p) {
switch(p->kind()) {
case 0: return "dragon";
case 1: return "ninja";
case 2: return "iceman";
case 3: return "lion";
case 4: return "wolf";
}
}
class HeadQuarter {
private:
vector<Warrior*> wr;
vector<int> ct;
int tot;
Warrior *_generate_warrior() {
if (wr[now] == &dragon_obj) return new WarriorDragon(tot, 1.0 * health / dragon_obj.get_init_health());
else if (wr[now] == &ninja_obj) return new WarriorNinja(tot);
else if (wr[now] == &iceman_obj) return new WarriorIceman(tot);
else if (wr[now] == &lion_obj) return new WarriorLion(tot, health);
else return new WarriorWolf(tot);
}
public:
int health, now;
HeadQuarter(int health) : health(health), now(-1), tot(0) { }
template<typename T> void add_warrior_type(T &instance) {
wr.emplace_back(&instance);
ct.emplace_back(0);
}
Warrior *generate_warrior() {
if (now == -2) return nullptr;
now = now == wr.size() - 1 ? 0 : now + 1;
if (health >= wr[now]->get_init_health()) {
++tot;
++ct[now];
health -= wr[now]->get_init_health();
return _generate_warrior();
} else
now = -2;
return nullptr;
}
void show_warrior() {
wr[now]->show();
}
};
class BattleField {
int n;
public:
Warrior **city[2];
BattleField(int n) : n(n) { // city_num = n
city[0] = new Warrior *[n + 2]();
city[1] = new Warrior *[n + 2]();
}
void event_5() {
for (int i = 0; i <= n + 1; ++i) {
if (city[0][i] != nullptr && city[0][i]->kind() == 3 && ((WarriorLion *)city[0][i])->loyalty <= 0) {
print_time();
printf("red lion %d ran away\n", city[0][i]->id);
delete city[0][i];
city[0][i] = nullptr;
}
if (city[1][i] != nullptr && city[1][i]->kind() == 3 && ((WarriorLion *)city[1][i])->loyalty <= 0) {
print_time();
printf("blue lion %d ran away\n", city[1][i]->id);
delete city[1][i];
city[1][i] = nullptr;
}
}
} // lions flee
void event_10() {
Warrior *x = city[1][1];
if (x != nullptr) {
x->one_step();
print_time(); printf("blue %s %d reached red headquarter with %d elements and force %d\n", getname(x), x->id, x->health, x->attack());
print_time(); puts("red headquarter was taken");
game_over = 1;
}
for (int i = 1; i <= n; ++i) {
x = city[0][i - 1];
if (x != nullptr) {
x->one_step();
print_time(); printf("red %s %d marched to city %d with %d elements and force %d\n", getname(x), x->id, i, x->health, x->attack());
}
x = city[1][i + 1];
if (x != nullptr) {
x->one_step();
print_time(); printf("blue %s %d marched to city %d with %d elements and force %d\n", getname(x), x->id, i, x->health, x->attack());
}
}
x = city[0][n];
if (x != nullptr) {
x->one_step();
print_time(); printf("red %s %d reached blue headquarter with %d elements and force %d\n", getname(x), x->id, x->health, x->attack());
print_time(); puts("blue headquarter was taken");
game_over = 1;
}
for (int i = n; i >= 1; --i) city[0][i] = city[0][i - 1];
city[0][0] = nullptr;
for (int i = 1; i <= n; ++i) city[1][i] = city[1][i + 1];
city[1][n + 1] = nullptr;
} // one step forward
int capture(Warrior *x, Warrior *y) {
int count = 0;
sort(y->w.begin(), y->w.end(), [](Weapon *p, Weapon *q) { return p->type > q->type || p->type == q->type && p->unbreaking < q->unbreaking; });
for (auto e = y->w.rbegin(); e != y->w.rend() && x->w.size() < 10; ++e) {
x->w.emplace_back(*e);
++count;
}
for (int i = 0; i < count; ++i) y->w.pop_back();
return count;
}
int capture_wolf(Warrior *x, Warrior *y) {
int count = 0;
sort(y->w.begin(), y->w.end(), [](Weapon *p, Weapon *q) { return p->type > q->type || p->type == q->type && p->unbreaking < q->unbreaking; });
for (auto e = y->w.rbegin(), s = e; e != y->w.rend() && x->w.size() < 10 && (*e)->type == (*s)->type; ++e) {
x->w.emplace_back(*e);
++count;
}
for (int i = 0; i < count; ++i) y->w.pop_back();
return count;
}
void event_35() {
for (int i = 1; i <= n; ++i) {
Warrior *x = city[0][i];
Warrior *y = city[1][i];
if (x != nullptr && y != nullptr) {
if (x->kind() == 4 && y->kind() == 4) continue;
int count = 0;
if (x->kind() == 4) {
if (count = capture_wolf(x, y)) {
print_time(); printf("red wolf %d took %d %s from blue %s %d in city %d\n", x->id, count, x->w.back()->get_name(), getname(y), y->id, i);
}
} else if (y->kind() == 4) {
if (count = capture_wolf(y, x)) {
print_time(); printf("blue wolf %d took %d %s from red %s %d in city %d\n", y->id, count, y->w.back()->get_name(), getname(x), x->id, i);
}
}
}
}
}
int attack_process(Warrior *x, Weapon *w, Warrior *y) {
int u;
switch(w->type) {
case 0:
u = x->attack() * 2 / 10;
y->health -= u;
return u > 0;
case 1:
u = x->attack() * 4 / 10;
y->health -= u;
if (x->kind() != 1)
x->health -= u >> 1;
--w->unbreaking;
return u > 0;
case 2:
u = x->attack() * 3 / 10;
y->health -= u;
--w->unbreaking;
return u > 0;
}
}
void event_40() {
for (int i = 1; i <= n; ++i) {
Warrior *x = city[0][i];
Warrior *y = city[1][i];
if (x == nullptr || y == nullptr) continue;
sort(x->w.begin(), x->w.end(), [](Weapon *p, Weapon *q) { return p->type < q->type || p->type == q->type && p->unbreaking < q->unbreaking; });
sort(y->w.begin(), y->w.end(), [](Weapon *p, Weapon *q) { return p->type < q->type || p->type == q->type && p->unbreaking < q->unbreaking; });
if (i & 1) {
auto px = 0, py = 0;
bool effective = 1;
while (1) {
if (x->health <= 0) break;
if (y->health <= 0) break;
if (x->w.empty() && y->w.empty()) break;
if (!effective && (x->w.empty() || x->w.back()->type == 0) && (y->w.empty() || y->w.back()->type == 0)) break; // ״̬²»·¢Éú±ä»¯
effective = 0;
if (!x->w.empty()) {
effective |= attack_process(x, x->w[px], y);
if (x->w[px]->unbreaking == 0) {
delete *(x->w.begin() + px);
x->w.erase(x->w.begin() + px);
} else
++px;
if (px == x->w.size()) px = 0;
}
if (x->health <= 0) break;
if (y->health <= 0) break;
if (!y->w.empty()) {
effective |= attack_process(y, y->w[py], x);
if (y->w[py]->unbreaking == 0) {
delete *(y->w.begin() + py);
y->w.erase(y->w.begin() + py);
} else
++py;
if (py == y->w.size()) py = 0;
}
}
} else {
auto px = 0, py = 0;
bool effective = 1;
while (1) {
if (y->health <= 0) break;
if (x->health <= 0) break;
if (x->w.empty() && y->w.empty()) break;
if (!effective && (x->w.empty() || x->w.back()->type == 0) && (y->w.empty() || y->w.back()->type == 0)) break; // ״̬²»·¢Éú±ä»¯
effective = 0;
if (!y->w.empty()) {
effective |= attack_process(y, y->w[py], x);
if (y->w[py]->unbreaking == 0) {
delete *(y->w.begin() + py);
y->w.erase(y->w.begin() + py);
} else
++py;
if (py == y->w.size()) py = 0;
}
if (y->health <= 0) break;
if (x->health <= 0) break;
if (!x->w.empty()) {
effective |= attack_process(x, x->w[px], y);
if (x->w[px]->unbreaking == 0) {
delete *(x->w.begin() + px);
x->w.erase(x->w.begin() + px);
} else
++px;
if (px == x->w.size()) px = 0;
}
}
}
print_time();
if (x->health > 0 && y->health > 0) {
printf("both red %s %d and blue %s %d were alive in city %d\n", getname(x), x->id, getname(y), y->id, i);
if (x->kind() == 0) {
print_time();
printf("red dragon %d yelled in city %d\n", x->id, i);
}
if (y != nullptr && y->health > 0 && y->kind() == 0) {
print_time();
printf("blue dragon %d yelled in city %d\n", y->id, i);
}
} else if (x->health > 0) {
printf("red %s %d killed blue %s %d in city %d remaining %d elements\n", getname(x), x->id, getname(y), y->id, i, x->health);
if (x->kind() == 0) {
print_time();
printf("red dragon %d yelled in city %d\n", x->id, i);
}
capture(x, y);
delete city[1][i];
city[1][i] = nullptr;
} else if (y->health > 0) {
printf("blue %s %d killed red %s %d in city %d remaining %d elements\n", getname(y), y->id, getname(x), x->id, i, y->health);
if (y != nullptr && y->health > 0 && y->kind() == 0) {
print_time();
printf("blue dragon %d yelled in city %d\n", y->id, i);
}
capture(y, x);
delete city[0][i];
city[0][i] = nullptr;
} else {
printf("both red %s %d and blue %s %d died in city %d\n", getname(x), x->id, getname(y), y->id, i);
delete city[0][i];
city[0][i] = nullptr;
delete city[1][i];
city[1][i] = nullptr;
}
}
}
void event_55() {
for (int i = 0; i <= n + 1; ++i) {
Warrior *x = city[0][i];
if (x != nullptr) {
int u = 0, v = 0, w = 0;
for (auto e : x->w) {
switch(e->type) {
case 0: ++u; break;
case 1: ++v; break;
case 2: ++w; break;
}
}
print_time(); printf("red %s %d has %d sword %d bomb %d arrow and %d elements\n", getname(x), x->id, u, v, w, x->health);
}
x = city[1][i];
if (x != nullptr) {
int u = 0, v = 0, w = 0;
for (auto e : x->w) {
switch(e->type) {
case 0: ++u; break;
case 1: ++v; break;
case 2: ++w; break;
}
}
print_time(); printf("blue %s %d has %d sword %d bomb %d arrow and %d elements\n", getname(x), x->id, u, v, w, x->health);
}
}
}
~BattleField() {
delete city[0];
delete city[1];
}
};
int main() {
freopen("dd.txt", "w", stdout);
for (int T, _ = (scanf("%d", &T), 1); _ <= T; ++_) {
int hp, n, time_limit;
scanf("%d%d%d%d", &hp, &n, &WarriorLion::k, &time_limit);
BattleField bf(n);
HeadQuarter red(hp);
red.add_warrior_type(iceman_obj), red.add_warrior_type(lion_obj);
red.add_warrior_type(wolf_obj), red.add_warrior_type(ninja_obj), red.add_warrior_type(dragon_obj);
HeadQuarter blue(hp);
blue.add_warrior_type(lion_obj), blue.add_warrior_type(dragon_obj);
blue.add_warrior_type(ninja_obj), blue.add_warrior_type(iceman_obj), blue.add_warrior_type(wolf_obj);
scanf("%d", &WarriorDragon::init_health);
scanf("%d", &WarriorNinja::init_health);
scanf("%d", &WarriorIceman::init_health);
scanf("%d", &WarriorLion::init_health);
scanf("%d", &WarriorWolf::init_health);
scanf("%d", &WarriorDragon::_attack);
scanf("%d", &WarriorNinja::_attack);
scanf("%d", &WarriorIceman::_attack);
scanf("%d", &WarriorLion::_attack);
scanf("%d", &WarriorWolf::_attack);
printf("Case %d:\n", _);
game_over = 0;
current_time = -5;
while (1) {
current_time += 5;
if (current_time > time_limit || game_over) break;
Warrior *x = red.generate_warrior();
if (x != nullptr) {
bf.city[0][0] = x;
print_time(); printf("red %s %d born\n", getname(x), x->id);
if (x->kind() == 3) {
printf("Its loyalty is %d\n", ((WarriorLion *)x)->loyalty);
}
}
x = blue.generate_warrior();
if (x != nullptr) {
bf.city[1][n + 1] = x;
print_time(); printf("blue %s %d born\n", getname(x), x->id);
if (x->kind() == 3) {
printf("Its loyalty is %d\n", ((WarriorLion *)x)->loyalty);
}
}
current_time += 5;
if (current_time > time_limit || game_over) break;
bf.event_5();
current_time += 5;
if (current_time > time_limit || game_over) break;
bf.event_10();
current_time += 25;
if (current_time > time_limit || game_over) break;
bf.event_35(); // ÇÀ×°±¸
current_time += 5;
if (current_time > time_limit || game_over) break;
bf.event_40();
current_time += 10;
if (current_time > time_limit || game_over) break;
print_time(); printf("%d elements in red headquarter\n", red.health);
print_time(); printf("%d elements in blue headquarter\n", blue.health);
current_time += 5;
if (current_time > time_limit || game_over) break;
bf.event_55();
}
}
return 0;
}