Разбор олимпиадной задачи — Железная дорога

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 1 неделя, 6 дн. назад.

  • Автор
    Сообщения
  • #5456
    @admin

    Задача взята с acmp.ru (Время: 1 сек. Память: 16 Мб Сложность: 26%):

    При строительстве новой железной дороги возникли проблемы. Дорога пролегает по холмистой местности, однако сами пути должны идти строго горизонтально. Поэтому руководство строительной компании приняло решение выровнять поверхность земли на этом участке. Главная проблема состоит в том, что привозить или вывозить землю на стройку стоит 10000$ за кубический метр. Поскольку бюджет железной дороги невелик, этого нельзя себе позволить.
    
    Поэтому главный инженер принял решение выровнять поверхность, используя только землю, из которой состоят холмы. Теперь самая сложная задача состоит в том, чтобы выяснить высоту над уровнем моря, на которой будет пролегать дорога. Это ответственное задание было поручено Вам.
    
    Через каждый метр от начала участка была измерена высота над уровнем моря. Напишите программу, которая по данным измерений рассчитывает искомую высоту. 
    
    Входные данные:
    
    Первая строка входного файла INPUT.TXT содержит количество N (1 < N ≤ 30000) точек, в которых была замерена высота. Вторая строка содержит результаты замеров – i-ое число строки содержит высоту над уровнем моря точки, находящейся на расстоянии (i-1) метр от начала участка. Все высоты – целые неотрицательные числа, не превосходящие 10000. Считайте, что между соседними точками измерений земная поверхность строго прямолинейна. 
    
    Выходные данные:
    
    В выходной файл OUTPUT.TXT выведите ответ на задачу с точностью, не меньшей 10^(-5).
    
    Пример 1:
    INPUT.TXT: 
    4
    0 1 1 0
    OUTPUT.TXT : 0.6666666667
    
    Пример 2:
    INPUT.TXT: 
    5
    2 2 2 2 2
    OUTPUT.TXT : 2.0000000000

    Из условия ясно, что чтобы решить задачу нужно найти «среднюю» высоту, но первый пример демонстрирует, что вычислить среднее арифметическое будет не достаточно. На самом деле, есть холмики известной высоты, соеденены они прямыми линиями. Следовательно если у нас есть два холмика высотами 1 и 4 метра — то в них не 5 «кубометров» земли, а больше. Это пояснит следующая картинка:

    Закрашенные треугольники — это то, что нужно добавить к сумме высот холмов. Площадь этих треугольников зависит от перепада высот соседних холмов, так если H[i] = A и H[i+1] = B, то площадь треугольника между холмами — это (|A-B| / 2).

    Решить задачу с помощью С++ можно следующим образом:

    #include <fstream>
    #include <vector>
    #include <iomanip>
    using namespace std;
    
    int main() {
      ifstream infile("input.txt");
      ofstream outfile("output.txt");
      
      int n;
      infile >> n;
      vector<double> points(n);
    
      for (int i = 0; i < n; i++)
        infile >> points[i];
      
      double sum = 0;
      
      for (int i = 0; i < n-1; i++) { 
        sum += points[i] + (points[i+1] - points[i])/2;   
      }
      sum /= (n-1);
      
      outfile << fixed << setprecision(10) << sum;
    }

    Интерес представляет цикл, в котором идет суммрование. Обрабатываются все точки кроме последней. При обработке i-той точки к сумме добавляется не только высота i-того холма, но и площадь треугольника между ней и (i+1)-ой.

    Обратите внимание, что если следующая точка выше предыдущей — то рассчет пойдет так, как было описано. А если ниже — то этот треугольник будет вычтен. Например для точек 4 1 мы добавим к сумме 4, а затем уменьшим это значение на величину перипада высот (1-4)/2.

    Полученная сумма делится на n-1, т.к. если у нас есть две точки — то дают они один «интервал», а для приведенного выше рисунка с 6 точками — таких интервалов 5.

    Наконец, вывести результат необходимо с заданной точностью, как видно из второго примера, выводить нужно даже незначащие нули. Для этого используется манипулятор fixed и setprecision.

Для ответа в этой теме необходимо авторизоваться.