Algorithm/eating-snake/main.cc

141 lines
3.5 KiB
C++
Raw Normal View History

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
2024-10-10 13:15:37 +00:00
#define ENABLE_LOG
struct snake {
int id;
int power;
snake(int id, int power) {
this->id = id;
this->power = power;
}
bool operator<(const snake &obj) const {
if (obj.power == power) return obj.id < id;
return obj.power < power;
}
bool operator>=(const snake &obj) const {
return power >= obj.power;
}
};
bool sort_by_id(snake a, snake b) {
return b.id > a.id;
}
2024-10-10 13:15:37 +00:00
bool eat(vector<snake> &vec, bool skip_sort = false, int initial_id = 0) {
if (vec.size() < 2) return true;
if (!skip_sort) {
sort(vec.begin(), vec.end());
}
#if defined(ENABLE_LOG)
for (auto item: vec) {
printf("eating log: \n");
printf("(%d, %d)\n", item.id, item.power);
}
#endif
2024-10-10 13:15:37 +00:00
if (!(vec[initial_id] >= vec[vec.size() - 1])) {
return true;
}
// If this snake ate the last snake
snake curr = vec[0];
snake last = vec[vec.size() - 1];
#if defined(ENABLE_LOG)
printf("%d gonna to eat %d\n", curr.id, last.id);
#endif
vec.pop_back();
2024-10-10 13:15:37 +00:00
vec[initial_id].power -= last.power;
sort(vec.begin(), vec.end());
if (vec[0].id != curr.id) {
bool will_be_eaten = false;
int strongest_curr_power = vec[0].power;
// Looking up if current snake will be eaten
for (auto it = vec.rbegin(); it < vec.rend(); it++) {
if (strongest_curr_power >= it->power) {
if (it->id == curr.id) {
// So bad, the new strongest snake will eat the current strongest snake
// Give up eating right now!
will_be_eaten = true;
break;
}
// No more thinking, just go for it
strongest_curr_power -= it->power;
}
}
if (will_be_eaten) {
#if defined(ENABLE_LOG)
printf("%d give up, cuz it will be eaten after ate that snake, new strongest snake %d\n", curr.id,
vec[0].id);
#endif
// It means the current snake going to be eaten
// Revert the action
for (auto &item: vec) {
if (item.id == curr.id) {
item.power = curr.power;
break;
}
}
vec.push_back(last);
}
}
#if defined(ENABLE_LOG)
printf("%d has ate %d\n", curr.id, last.id);
#endif
// Else, it means the current snake is still strong enough
// Going to see other snakes can be eaten...
return eat(vec, skip_sort = true);
}
int main() {
int count;
cin >> count;
vector<snake> snakes;
int t;
cin >> t;
for (int i = 0; i < t; i++) {
int a;
cin >> a;
snakes.emplace_back(i + 1, a);
}
eat(snakes);
cout << snakes.size() << endl;
for (int i = 0; i < count - 1; i++) {
int n;
cin >> n;
sort(snakes.begin(), snakes.end(), sort_by_id);
#if defined(ENABLE_LOG)
printf("alter log: \n");
for (const auto &item: snakes) {
printf("%d ", item.id);
}
printf("\n");
#endif
for (int j = 0; j < n; j++) {
int id, alter;
cin >> id >> alter;
if (snakes.size() < id) {
// Respawn
snakes.emplace_back(id, alter);
} else {
// Alter power
snakes[id - 1].power = alter;
}
}
eat(snakes);
cout << snakes.size() << endl;
}
}