Это основано на задаче на Kattis, называемой Galactic Collegiate Programming Contest. Я пытался создать решение на c++, и оно работает для маленьких чисел, таких как их тестовый ввод:
3 4
2 7
3 5
1 6
1 9
Но как только я ввожу большие числа, которые они дают, программа внезапно зависает во время выполнения и не выдает никаких результатов. В коде, который я прикладываю, также есть тестовые случаи для этих больших чисел. Есть ли какая-то утечка памяти или что-то подобное, вызывающее эту проблему? И как я мог бы это исправить?
#include <iostream>
#include <vector>
// ТЕСТ ТЕСТ ТЕСТ ТЕСТ
#include <cstdlib>
#include <ctime>
using namespace std;
struct Team
{
int solP; // Количество решенных задач
int numP; // Количество штрафов
int rank;
};
int main()
{
srand(time(0)); // ТЕСТ ТЕСТ ТЕСТ ТЕСТ
vector<Team> teams; // 0 обозначает команду 1
vector<int> favoriteTeam; // Заполнен рангами любимой команды
vector<int> rank; // Заполнен рангами с последнего события
int numTeams;
int numEvents;
//cin >> numTeams >> numEvents; // Считывание строки 1 // ТЕСТ ТЕСТ ТЕСТ
numTeams = (rand() % (int)10e5) + 1;
numEvents = (rand() % (int)10e5) + 1;
// ТЕСТ ТЕСТ ТЕСТ
teams.resize(numTeams);
favoriteTeam.resize(numEvents);
rank.resize(numTeams);
for (int i = 0; i < numTeams; i++)
{
Team temp;
temp.solP = 0;
temp.numP = 0;
temp.rank = 1;
teams[i] = temp;
}
for (int i = 0; i < numEvents; i++)
{
int t, p;
//cin >> t >> p; ТЕСТ ТЕСТ ТЕСТ
t = (rand() % numTeams) + 1;
p = (rand() % 1000) + 1;
// ТЕСТ ТЕСТ ТЕСТ
++teams[t - 1].solP;
teams[t - 1].numP += p;
// ВЫЗОВ ДЛЯ УПОРЯДОЧИВАНИЯ
int modifier;
int bestIndex;
vector<bool> tie(numTeams);
vector<bool> used(numTeams, false);
// Настройка вектора рангов
for (int i = 0; i < numTeams; i++)
{
bestIndex = i;
for (int j = 0; j < numTeams; j++)
{
if (i == j || used[j]) continue;
if (used[i] || teams[j].solP > teams[bestIndex].solP || teams[j].solP == teams[bestIndex].solP && teams[j].numP <= teams[bestIndex].numP)
{
bestIndex = j;
}
}
rank[i] = bestIndex;
used[bestIndex] = true;
}
// Настройка вектора ничьих
for (int i = 0; i < numTeams; i++)
{
if (i != 0 && teams[rank[i]].solP == teams[rank[i - 1]].solP && teams[rank[i]].numP == teams[rank[i - 1]].numP)
{
tie[i] = true;
}
else tie[i] = false;
}
// Установка ранга для каждой команды
modifier = 0;
for (int i = 0; i < numTeams; i++)
{
if (tie[i]) modifier++;
teams[rank[i]].rank = i + 1 - modifier;
}
// Установка вывода
favoriteTeam[i] = teams[0].rank;
}
//cout << endl;
for (int i = 0; i < numEvents; i++)
{
cout << favoriteTeam[i] << endl;
}
cout << clock() / (double)CLOCKS_PER_SEC << endl;
return 0;
}
Ответ
Проблема, с которой вы столкнулись, может быть связана с чрезмерным использованием памяти и неэффективными алгоритмами, которые могут привести к превышению времени выполнения или утечкам памяти при работе с большими объёмами данных. Давайте рассмотрим несколько аспектов вашего кода и предложим возможные решения.
Проблемы в коде
-
Инициализация векторов и их размер:
Вы используетеvector<Team> teams
и два других вектора, что может занять значительное количество памяти. Когда вы создаетеnumTeams
илиnumEvents
, которые могут достигать 1 миллиона, вы находитесь на грани аренды памяти, и ваш компьютер может просто не иметь достаточно оперативной памяти для выполнения кода. -
Алгоритм сортировки:
Ваш текущий алгоритм для определения рангов команд — это алгоритм с временной сложностью O(n^2), который будет работать неэффективно с большими размерами векторов. Это также может привести к замедлению выполнения программы. - Логику использования переменной
used
:
Ваша переменнаяused
может вызвать дополнительные проверки, что делает ваш алгоритм ещё более неэффективным.
Рекомендуемые изменения
-
Изменить алгоритм сортировки:
Вместо использования вложенного цикла для определения рангов, вы можете создать отдельный вектор, который будет хранить пары (объект команды и её индекс), после чего отсортировать его по убыванию решенных задач и по возрастанию штрафов.#include <algorithm> // Используйте стандартный метод сортировки vector<pair<Team, int>> indexedTeams; for (int i = 0; i < numTeams; ++i) { indexedTeams.emplace_back(teams[i], i); } sort(indexedTeams.begin(), indexedTeams.end(), [](const auto& a, const auto& b) { if (a.first.solP != b.first.solP) return a.first.solP > b.first.solP; return a.first.numP < b.first.numP; });
-
Оптимизация памяти:
Попробуйте выделить память более экономно. Например, если вам не нужна слишком большая память, попробуйте использоватьstd::vector.reserve()
, чтобы избежать множества переполнений при добавлении элементов. - Использовать
unordered_map
для хранения штрафов:
Рассмотрите возможность использованияstd::unordered_map
для хранения и обработки команд, если это приемлемо для вашей задачи.
Пример исправленного кода
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;
struct Team {
int solP; // количество решенных задач
int numP; // штраф
int rank;
};
int main() {
srand(time(0));
int numTeams = (rand() % (int)10e5) + 1;
int numEvents = (rand() % (int)10e5) + 1;
vector<Team> teams(numTeams, {0, 0, 0});
vector<int> favoriteTeam(numEvents);
for (int i = 0; i < numEvents; ++i) {
int t = rand() % numTeams;
int p = (rand() % 1000) + 1;
++teams[t].solP;
teams[t].numP += p;
vector<pair<Team, int>> indexedTeams;
for (int j = 0; j < numTeams; ++j) {
indexedTeams.emplace_back(teams[j], j);
}
sort(indexedTeams.begin(), indexedTeams.end(), [](const auto& a, const auto& b) {
if (a.first.solP != b.first.solP)
return a.first.solP > b.first.solP;
return a.first.numP < b.first.numP;
});
for (int j = 0; j < numTeams; ++j) {
teams[indexedTeams[j].second].rank = j + 1;
}
favoriteTeam[i] = teams[0].rank;
}
for (int i = 0; i < numEvents; ++i) {
cout << favoriteTeam[i] << endl;
}
return 0;
}
Заключение
Теперь ваш алгоритм должен работать более эффективно и устойчиво, даже при больших вводах данных. Убедитесь, что вы тестируете код с различными размерами входных данных, чтобы гарантировать, что он обрабатывается в течение разумного времени и с достаточной памятью.