Боже! Врятуй мене#1575

Боже! Врятуй мене (Розбір)

Позначимо через очікуваний час, через який можна вибратися з кімнати в безпечне місце. Тоді цей час виражається наступним чином:

P = \sum_{i=1}^n p_i \cdot t_i,

де t_i — час виходу в безпечне місце, якщо вибрати -ті двері. Очевидно, що t_i = x_i, якщо x_i > 0. Якщо x_i < 0, то для того щоб вибратися, потрібно спочатку витратити час -x_i на повернення в кімнату, а потім час на повторну спробу виходу. Таким чином, у цьому випадку t_i = -x_i + P.

У результаті отримуємо лінійне рівняння відносно . Побудувати і розв’язати це рівняння можна за час , де — кількість дверей.

Приклад

Розглянемо перший тест. Складемо рівняння:

P = 0.33 * 2 + 0.33 * (3 + P) + 0.34 * (5 + P),

звідки 0.33 \cdot P = 3.35 або P = 10.151515.

Реалізація алгоритму

Рішення лінійного рівняння будемо проводити наступним чином. Всі доданки, що містять множник , перенесемо вліво, а їх коефіцієнти будемо зберігати в змінній . Всі константи зберемо праворуч і збережемо в змінній . Спочатку встановимо left = 1 і right = 0.

Читаємо пар чисел та .

left = 1.0; right = 0.0;
scanf("%d",&n);
for(j = 0; j < n; j++)
{
  scanf("%lf %lf",&x, &p);
  if (x < 0.0)
  {
    left -= p;
    right += p * (-x);
  } else
      right += x * p;
}

Отримали рівняння left \cdot P = right. Якщо left = 0, то вибратися з кімнати неможливо (не існує дверей, що ведуть у безпечне місце). В іншому випадку шуканий час можна обчислити як P = right / left.

if (left > 0.0)
{
  res = right / left;

Виводимо відповідь. Змінній відповідає номер тесту.

  printf("Case %d: %.2lf\n",i,res);
} else
  printf("Case %d: God! Save me\n",i);