Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 12.02.2013, 21:37   #1
0x44616E69696C
 
Регистрация: 04.01.2013
Сообщений: 5
Вопрос ЕГЭ C4 (C++)

http://scool4.zxq.net/Q/

Вот, попробовал, не работает.

Сначала выводит 1 без ключа, потом выводит не все что должна.
Почему программа себя так ведет? Можно ли такое решение, даже рабочее назвать "эффективным"?
Может есть идеи?
И заодно, если не сложно, посоветуйте книжку по алгоритмам в общем, составление, оптимизация.
0x44616E69696C вне форума Ответить с цитированием
Старый 12.02.2013, 23:28   #2
ep1a
Пользователь
 
Регистрация: 30.01.2013
Сообщений: 12
По умолчанию

0x44616E69696C, я в свое время решал много вариантов ЕГЭ, и потом без проблем его сдал, он несложный. Еще лазил по всяким форумам и сайтам, видел всякие красивые методы решения различных задач. Также есть сайты со списком задач - можно их туда же отправлять на проверку - пример: acmp.ru
ep1a вне форума Ответить с цитированием
Старый 13.02.2013, 11:10   #3
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

1)
Цитата:
for (int i=0; i<=N; i++)//тут я думаю все понятно.
Мне непонятно. Цикл отработает N+1 раз.
2) else-ветка вывода мне непонятна совершенно. Почему бы тупо не вывести первые три фирмы, а дальше выводить фирмы, пока частота их упоминания равна частоте упоминания третьей?
Цитата:
Можно ли такое решение, даже рабочее назвать "эффективным"?
Да, вполне.
Abstraction вне форума Ответить с цитированием
Старый 13.02.2013, 14:33   #4
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
Почему бы тупо не вывести первые три фирмы, а дальше выводить фирмы, пока частота их упоминания равна частоте упоминания третьей?
потому что фирмы в мапе у него упорядочены по алфавиту, но не по частоте.
Тут нет решения, эффективным называть нечего. В ветке else какие-то отстои.

Код:
for (int k = 1, counter = 0;counter<3; k++)//цикл по числам от 1
                {
                        for (f=firm.begin(); f!=firm.end(); f++)//обход map f -- итератор, см. выше.
                        {
                                if((*f).second==k) //сравниваем все числовые данные map с текущим
Вы берете все k от 1 до черт знает чего и ищите это к в map - это ужасно. Тут сложность даже не O(n^2).

Т.е. если у меня есть всего 4 фирмы и каждая из них встречается 1000 раз - будет 3 * 1000 * 4 итераций внутреннего цикла в худшем случае (тут не должно быть более 3*4 итераций)

Поиск наибольшего элемента массива - O(n)
Если вы выполните такой поиск 3 раза -алгоритм будет не самым оптимальным, но значительно лучше вашего.

Можно все значения засунуть в еще один мап и дальше сделать как абстракшн советует, но это будет неоптимально по памяти (там в требованиях про это написано).
rrrFer вне форума Ответить с цитированием
Старый 13.02.2013, 14:46   #5
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
потому что фирмы в мапе у него упорядочены по алфавиту, но не по частоте.
/me идиот. Да, карта упорядочивает по ключу, что даёт нам быстрый поиск названий. Под занавес надо переупорядочить по значениям -
Код:
bool ComparePairs(std::pair<std::string, int> a, std::pair<std::string, int> b){
  return a.second() < b.second();
}
//...
std::vector< std::pair<std::string, int> > sorted (firm.begin(), firm.end());
std::sort(sorted.begin(), sorted.end(), ComparePairs);
Abstraction вне форума Ответить с цитированием
Старый 13.02.2013, 19:05   #6
0x44616E69696C
 
Регистрация: 04.01.2013
Сообщений: 5
По умолчанию

бррр.. задолбало: переписал, в первом цикле изменил условие на

Код:
for (int i=0; i<N; i++)
отрабатывает N-1 раз, я не понимаю. А функция Out первый раз всегда выводит просто единицу, но мне непонятно откуда она берется.
0x44616E69696C вне форума Ответить с цитированием
Старый 13.02.2013, 19:25   #7
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
А функция Out первый раз всегда выводит просто единицу, но мне непонятно откуда она берется.
ставишь точку останова в Out, выполняешь программу до нее, смотришь на значения которые она выводит и пытаешь догадаться ) если не получается - выполняй программу по шагам от начала до тех пор, пока единицу не выведет.
Цитата:
Под занавес надо переупорядочить по значениям -
можно конешно, но сортировка всего списка - это долго. Этож не просто так задача, а часть "С" ЕГЭ xD.
Я думаю, решить ее можно за линейное время )
Цитата:
переписал
Выше тебе советовали выкинуть map, пользы тебе от него не будет

-------добавил:

Держи вот кусок кода:
Код:
#include <fstream>
#include <set>
#include <string>
#include <algorithm>
#include <iostream>
int main() {
  const int NNUM = 3;
  std::multiset<std::string> set;
  std::ifstream ifst("input.txt");
  int v[NNUM] = {0}, num, n;
  
  auto change = [&v](int val) {
    auto t = std::min_element(v, v + NNUM);
    if (*t < val) (*t) = val;
  };
  
  ifst >> n; ifst.get();
  for (int i = 0; i < n; ++i) {
    const int LEN = 64;
    char cbuff[LEN];
    ifst.getline(cbuff, LEN);
    set.insert(cbuff);
  }
  ifst.close();
  
  std::string buff = *set.begin();
  num = 0;
  for (auto t : set) {
    if (t == buff)
      ++num;
    else {
      change(num);
      num = 1;
      buff = t;
    }
  }
  change(num);
  
  for (auto t : v)
    std::cout << t << std::endl;
}
за линейное время рассчитывается 3 наибольших значения количества вхождения слов с файла.
Тебе остается в еще одном цикле вывести значения, которые встречаются заданное число раз (число то уже известно) - это тоже можно сделать за линейное время, почти также.
Сложность алгоритма останется линейной.

Последний раз редактировалось rrrFer; 13.02.2013 в 20:10.
rrrFer вне форума Ответить с цитированием
Старый 14.02.2013, 12:49   #8
0x44616E69696C
 
Регистрация: 04.01.2013
Сообщений: 5
По умолчанию

Цитата:
Выше тебе советовали выкинуть map, пользы тебе от него не будет
Понял, я упустил значительную деталь в описании. Надо чтобы рядом с названием выводилось кол-во упоминаний.

Цитата:
Держи вот кусок кода:
Спасибо! C++ 11 --- это круто, всю ночь изучал нововведения, понял что мой учебник STL протух. Кстати, на JavaScript похоже.
0x44616E69696C вне форума Ответить с цитированием
Старый 14.02.2013, 12:58   #9
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,577
По умолчанию

Цитата:
Понял, я упустил значительную деталь в описании. Надо чтобы рядом с названием выводилось кол-во упоминаний.
но решение выше это не портит. Тебе надо дописать цикл, очень похожий на тот, в котором вычисляется массив v. там ты также должен будешь рассчитывать num (абсолютно также как это делается в примере) и если в массиве v есть значение num - то выводишь строку (в примере это переменная t), (а num в этом случае и есть то самое " кол-во упоминаний.").
rrrFer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
С4 Егэ на Си interfeys Помощь студентам 23 29.11.2012 20:25
С4 Егэ на Си interfeys Помощь студентам 2 19.11.2012 10:18
ЕГЭ С1,С2,С3 ПАСКАЛЬ alex14111 Паскаль, Turbo Pascal, PascalABC.NET 7 03.03.2011 20:51
ЕГЭ Xcopy Помощь студентам 6 05.02.2010 14:44