Задать вопрос
  • Как вырезать область изображения под контуром, Алгоритм?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    FillPolygon работает через обход в ширину.

    Сначала одним циклом покрасьте все точки контура.
    Потом берите любую точку внутри полигона, красьте ее и кладите в очередь. Пока очередь не пуста берете точку оттуда, берете 4 или 8 ее соседей и если они не покрашены еще - красите их и кладете в очередь.

    Может быть сложность с выбором самой первой точки внутри полигона. Но тут можно аккуратно пройтись вдоль полигона против часовой стрелки и взять первую непокрашенную точку слева относительно обхода. Тут можно для каждой точки найти вектора на двух соседей по контуру, потом перебрать 4-8 соседних пиксилей и взять тот непокрашенный, вектор на который лежит между двумя векторами вдоль контура.
    Ответ написан
    Комментировать
  • Почему в массив записываются числа не и указанного диапазона?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    *p = (rand( )%100 - 50);
    for (int i = 1; i < k; i++) {
      *(p + 1) = -i * * (p + i - 1);
    }


    Можете вообще объяснить, что этот код делает? Зачем он это делает? Что вы хотели, чтобы он делал?

    Помимо этого, вместо *(p+X) можно писать p[X]. Так понятнее. У вас тут явно не к месту арифметика указателей приплетена.

    А так, код работает так, как написан. Первое число в массиве заполняется случайным от -50 до 49, второе число много раз переписывается чем-то умноженным на какое-то другое число массива, остальные числа не заполняются вообще.

    Поскольку массив у вас локальный, то он нулями не инициализируется. Поэтому там изначально случайный мусор. Поэтому все, кроме первого элемента так и будет случайным мусором.
    Ответ написан
  • Как правильно освобождать память?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    В деструкторе удаляйте, только если память не nullptr или длина не 0.
    Ответ написан
    Комментировать
  • Из-за чего может быть access violation при решении этой задачи?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    access violation явно говорит о проблеме работы с памятью.

    Единственное спорное место - это ввод. Может в файле есть лишние переводы строк или кривые тесты (пропущено какое-то число). Ваша программа, похоже, в этом случае попытается обратиться к N[1] и упадет, потому что в строке только 1 или вообще 0 чисел.

    Перепишите ввод. Сделайте класс, который хранит текущий массив токенов. При запросе следующего - возвращает следующий, если токенов больше нет - читает еще строку, пока в ней не окажутся токены.

    Ну или читайте тупо функциями чтения чисел. В этой задаче входной файл маленький - можно спокойно читать по одному числу, даже если это будет медленнее.
    Ответ написан
  • Из за чего появляется ошибка ошибка ld returned 1 exit status?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Выше написанно undefined reference to 'processingArray(int*, int)'


    Ну вот. У вас функция processingArray объявлена, но нигде не реализована. Тело функции где? Поскольку вы ее объявили, компилятор это безобразие проглатил и понадеялся, что эта функция реализована в другом файле и на этапе линковки она найдется. Но линкер ее не нашел, потому что ее нигде и нет.

    Вы, видимо, не все из учебника переписали. Там после функции main скорее всего идет реализация функции processingArray.
    Ответ написан
    7 комментариев
  • Как решить проблему Segmention Fault?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Segmentation fault - это ошибка работы с памятью. Или выход за границы массива, или что-то не так с указателями.

    Я подозреваю, что в файле у вас не 50 строк (мне лень считать). Вот вы и вылезаете за границу массива.

    Ну или там какие-то лишние переводы строк, пробелы имеются. поэтому fin.eof() не выполняется после считывания последней строки. Потом вы пытаетесь что-то еще прочитать, но получаете назад пустую строку. Это бы не было проблемой, но вы потом пытаетесь это все запихать в 51-ый элемент массива.

    Советую вместо define N и статического массива использовать std::vector. В цикле считывания файла делайте push_back нового объекта в вектор (а еще лучше, emplace_back для экономии лишнего копирования).

    При выводе берите size() у вашего вектора.

    Если вы в выводе заметите лишнюю книгу в конце с пустыми данными, то можно добавить проверку при вводе - если хоть одна из 5 строк пустая - то не надо создавать новую книгу.
    Ответ написан
    Комментировать
  • Как составлять header файл для статической библиотеки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    А зачем это делать? Чем вас 8 хедеров не устраивают? Если уж так хочется сэкономить строчки в коде пользователей библиотеки, то можно воспользоваться рекурсивностью препроцессора и сделать хедер с 8 инклудами. Копипастить код точно не надо.
    Ответ написан
    1 комментарий
  • Перебрать все комбинации массивов строк?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Рекурсивная функция должна принимать текущий набор строк и номер следующего массива. Функция циклом перебирает строку из следующего массива, добавляет эту строку к текущему набору и вызывается рекурсивно. После вызова последнюю строку надо из текущего набора удалить. Если в начале функции вы видите, что обработаны уже все массивы - выводите текущий набор в ответ и возвращайтесь из функции.

    Еще, естественно, надо передавать в функцию массив массивов строк - ваши исходные данные.
    Ответ написан
    Комментировать
  • Нужно ли строго проверять if?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    А почему не рассматривается третий вариант? Что-нибудь вроде
    if (ToString(exampleVar)[0].length() == 4) alert(1)


    Умышленно писать === true, конечно может быть иногда оправданно в языках без строгой типизации, но в целом это довольно редко оправданная вещь.
    Ответ написан
    Комментировать
  • В чём ошибка реализации алгоритма Прима?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    if ((matrix[i][j] < minValue[j]) && (isPartOfOutputTree[j] == false))


    Вот тут ошибка. Ведь i - это номер итерации,а совсем не только что включенная в дерево вершина, относительно которой надо сделать релаксацию.
    Ответ написан
  • Почему при копировании файлов получаются битые файлы?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Аккуратно выведите куда-нибудь параметры, которые вы передаете в функцию создания symlink.

    Похоже, проблема в том, что вы передаете относительные, а не абсолютные пути в качестве цели для линка.
    При использовании функции копирования это, возможно, и не будет проблемой.
    Ответ написан
    8 комментариев
  • Как обвести множество точек на карте?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Вот алгоритм выделения граней планарного графа: https://e-maxx.ru/algo/facets

    Сначала вам придется попересекать отрезки друг с другом и получить граф: вершины - точки пересечения и концы отрезков, ребра - куски отрезков. Потом выделяете алгоритмом выше внешнюю и внутренние грани.

    Потом их сглаживаете. Внешнюю грань - наружу, внутренние - внутрь. Тут придется как-то эвристически действовать. Например, берете любую точку на контуре, если две ее соседние достаточно близки, то выкидываете текущую точку. Если внутренняя грань становится достаточно маленькой по площади - выкидываете ее целиком.

    Upd: Дополнение - выбрасывать можно только точки, "вогнутые" внутрь полигона, такие, что их удаление только сделает внешнюю часть больше, а внутреннюю меньше.

    В итоге, если удачно подобрать границы в алгоритме выше, то получится примерно как у вас на картинке.
    Ответ написан
    Комментировать
  • Как удалить первый элемент однонаправленного списка в с++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С односвязными списками сложно - надо знать предыдущий элемент, чтобы у него поменять ссылку на следующий через удаляемый элемент. Можно или поддерживать 2 указателя на 2 соседних элемента, или смореть на следующий элемент через next, пока у вас есть указатель на предыдущий к нему.

    Еще отдельная проблема с удалением первого элемента, потому что там менятся должна не ссылка next у предыдущего элемента, а ссылка на начало списка. Эту проблему можно решить по разному. Например, можно вместо указателя head держать один элемент списка без значения. Тогда указатель на начало списка будет менятся также как и любой другой. Фактически, в любом списке всегда будет один фиктивный элемент. Этот способ также предподчителен для работы с двусвязными списками. Тогда список как бы замыкается в кольцо и не надо разбирать отдельно ни случай первого, ни случай последнего элемента. Мне больше нравится другой метод - можно помнить не предыдущий элемент, а указатель-на-указатель, который надо будет поменять.

    node** prev_link = &head;
    node* cur = head;
    for  (node* cur = head; cur != nullptr; cur = cur->next) {
      if (cur->val == to_del) {
        *prev_link = cur->next;
        delete cur;
        break;
      }
      prev_link = &cur->next;
    }
    Ответ написан
    1 комментарий
  • Возможен ли треугольник по стороне, углу и пропорциональным сторонам?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Треугольник можно составить из любых трех отрезков, пока выпонляется неравенство труегольника a+b > c, a+c > b, b+c > a. достаточно проверять только одно из них - максимальное число должно быть меньше суммы остальных. Но если не очевидно, какое из них максимальное, то можно проверять все три.

    Итак, дано только A и k, так?

    Чтобы как-то угол связать со сторонами надо воспользоваться теоремой косинусов:

    c^2 = a^2+b^2-2*a*b*cosA.
    подставив суда b=ck, получим
    с^2 = a^2+k^2c^2-2*k*a*c*cosA

    Это квадратное уравнение, связывающее C и A. Можно решить его относительно a (c - параметр) и вы получите а, выраженное через с.

    Ну и в конце надо проверить, что a+b > c, a+c > b, b+c > a, подставив туда найденные формулы для b и a через c. В этих неравенствах будут известные cosA, sinA, k и неизвестная с. Поскольку тругольник по углу и соотношению сторон можно масшабировать, то неравнество должно выполнятся для всех c. Но на самом деле в этих неравенствах все c можно будет тупо сократить. Какие-то из них можно сразу же выкинуть, если рассмотреть 2 случая k>1 и k<=1. Ну а как их дальше решать - думайте сами.
    Ответ написан
    3 комментария
  • Как исправить ошибку "Нарушение прав доступа при записи по адресу"?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Эта ошибка означает, что вы пишите в какую-то память, которая вам не принадлежит.

    Или у вас там неинициализированный указатель, или выход за границы массива, или что-то подобное. Надо присмотреться ко всем указателям в программе.

    Можно во время отладки нажать на "продолжить" и тогда дебаггер остановится именно на той инструкции, которая вызвала ошибку. Дальше уже можно смотреть, в какую переменную вы там пишите и откуда она взялась.

    Падает оно потому, что нельзя string читать и писать в файл вот так, просто интенрпретируя память объекта как char*. Потому что string содержит в себе указатели на динамически выделенную память.

    Поэтому, когда вы его (в составе AutoBase) пишите в файл а потом читаете, вы получаете указатель на адрес, который был жив вместе со старым экземпляром класса. Однако, после удаления этого старого экземпляра, этот адрес уже вам не принадлежит.

    Вы можете так писать в файл только структуры из простых типов, и то не всегда (там всякое выравнивание может сыграть с вами злую шутку). Надо писать собственные методы сериализации и десериализации. Строку можно сохранять, например, как длину и потом столько байт, сколько нужно. Тогда при считывании вы сначала чистаете сколько-то байт размера, а потом нужное количество байт в саму строку.
    Ответ написан
    1 комментарий
  • Как сгенерировать результаты за тест случайным образом, с заданной вероятностью каждого результата?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Шансы 1:3:3:1. Генерируйте случайное число от 0 до 7. При 0 - выдавайте случайное число < 50. При 1-3 - случайное число от 50 до 74, при 4-6 - выдывайте ответ от 75 до 89, при 7 выдавайте число от 90 до 100.

    Какие именно числа из промежутка выдавать в задании не сказано. Можете как-то случайно равновероятно или как-то нормально генерировать или вообще выдывать середину промежутка всегда.
    Ответ написан
  • Функция с параметром указателем на другую функцию. Как сделать правильно чтобы не выдавало ошибку?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    analiz(func(n));

    Вот тут вы вызываете функцию func и передаете результат ее работы в analiz. Хотя analiz хочет получать функцию. Надо делать так: analiz(&func);
    Ответ написан
    4 комментария
  • Как найти общую часть у вещественных чисел?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Через битовые операции вы ничего не сделаете, потому что у вас, судя по всему, надо найти общие цифры в десятичной системе счисления. Вообще найти десятичные цифры у вещественных чисел - весьма сложная операция.

    Я думаю, вам остается только вывести оба числа в строки в каком-нибудь фиксированном формате и дальше сравнивать посимвольно.
    Ответ написан
  • Как занести в char int?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Используйте sprintf. Только сначала выделите достаточно памяти под строку.

    Если чисел не фиксированное количество и вы не можете их все одним вызовом записать, то вам надо сохранять возвращенное sprintf занчение и следующее число записывать уже сдвигаясь на это число байт.
    Ответ написан
    Комментировать
  • Как лучше оптимизировать такие действия с массивами?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Во-первых, может быть проблема со вводом. cin и cout работают медленно с большими объемами данных. Или читайте через scanf, или можно отключить синхронизацию с stdio.

    Во-вторых, описанная вами структура данных быстродействие не убъет, но мне не понятно, чем она поможет в задаче.

    Вам точно понадобятся map-ы из строки во что-то еще. В питоне вы наверняка использовали словари (использовали строки в виде ключа в массиве), вот это оно и будет в с++. Можно поэксперементировать std::unordered_map может быть побыстрее std::map. А вообще, особенно быстрое решение вы можете получить используя cтруктуру данных бор (оно же trie). Правда, ее придется самостоятельно писать.
    Ответ написан
    3 комментария