Вот программа:
#include <iostream>
#include <algorithm>
using namespace std;
void check(int array[],int size);
int Guest = 0;
int main()
{
int n;
cin>>n;
if(n == 1){
int l;
cin>>l;
cout<<l/2+l%2;
return 0;
}
int *arr = new int[n];
for (int i = 0; i < n; ++i) {
cin>>arr[i];
}
check(arr,n);
return 0;
}
void check(int arr[], int size){
sort(arr,arr + size);
if(abs(Guest - arr[size-1]) == 1){
cout<<max(Guest,arr[size-1]);
return ;
}
arr[size-1]--;
Guest++;
check(arr,size);
}
что она должна делать: Вот
Говорят программа слишком медленная.Как исправить?
Ну на каждом шагу пересортировывать - это, конечно, не годится.
Значительно более быстрый вариант - с использованием бинарного поиска. Вкратце:
Отсортируем массив по возрастанию.
Создадим второй массив с накопленной суммой (С[i] = C[i-1] + A[i]
)
Выберем индекс i
(на рисунке i=4)
Если срезать стопки блинов по высоте A[i]
, то останется R = С[i] + A[i]*(N-i)
(серое + красное), а остальное Q =C[N]-R
(синее) перейдёт неофиту.
Если Q > A[i]
, то i
надо увеличивать, если меньше - уменьшать.
Задачу можно решить за один проход по предварительно отсортированному в возрастающем порядке массиву исходя из следующего уравнения:
a - x >= c + x * (i + 1)
где:
Соответсвенно:
x = (a - c) / (i + 2)
Алгоритм:
int64_t c = 0;
int64_t m = arr[0]; // искомый результат
for (int i=0; i<arr.size(); ++i) {
int64_t a = arr[i];
if (a <= c) break; // #1
int64_t x = (a - c) / (i + 2);
if (i < arr.size() - 1 && x > a - arr[i + 1]) { // #2
x = a - arr[i + 1];
}
c += (i + 1) * x;
m = a - x;
}
Коментарии:
(a > c)
.Полностью пример:
#include <algorithm>
#include <iostream>
#include <vector>
template <typename T>
void print(const std::string& title, const T& arr)
{
std::cout << title;
for (const auto& x: arr) {
std::cout << ' ' << x;
}
std::cout << std::endl;
}
int main(int argc, char** argv)
{
std::vector<int64_t> arr {1, 19, 1, 15, 20};
print("orig: ", arr);
std::sort(arr.begin(), arr.end(), std::greater<decltype(arr)::value_type>());
print("sorted: ", arr);
int64_t c = 0;
int64_t m = arr[0];
for (int i=0; i<arr.size(); ++i) {
int64_t a = arr[i];
if (a <= c) break;
int64_t x = (a - c) / (i + 2);
if (i < arr.size() - 1 && x > a - arr[i + 1]) {
x = a - arr[i + 1];
}
c += (i + 1) * x;
m = a - x;
}
for (auto& x: arr) {
if (x < m) break;
x = m;
}
arr.push_back(c);
print("output: ", arr);
std::cout << "m=" << m << " c=" << c << std::endl;
return 0;
}
Результат:
orig: 1 19 1 15 20
sorted: 20 19 15 1 1
output: 14 14 14 1 1 12
m=14 c=12
Upd: Важный момент - при проходе по массиву, на самом деле, нету смысла уменьшать элементы массива. Именно это и реализовано. Двигаясь от начала массива, алгоритм оценивает достаточен ли запас свободного места в 'тарелке нового гостя'. И если это так, то расчитывается новый максимум m.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Занимаюсь подписанием строкиОбычная подпись проходит
Пытаюсь освоить новый для себя c++ и пишу приложение "blackjack"На данный момент уже долгое время ломаю голову над этой ошибкой - Необработанное...
Собственно то почему этот код должен выбросить ошибку написано в статье: http://scrutatorme/post/2015/12/30/pointers_demystified_p2