Проблема с решением, которое вы описываете в своем вопросе, заключается в том, что необходимо учитывать экспоненциально большое количество подмножеств состояний. Это сделает решение невозможным, даже если набор состояний относительно мал (например, 50). Однако вы можете решить эту проблему с помощью динамического программирования за время O(NS), где N — общее количество голосов выборщиков, а S — количество штатов.
Начните с массива P размера N+1. Запись i в массиве будет представлять вероятность того, что республиканец получит i голосов выборщиков. Он имеет размер N+1, потому что количество голосов, которое они могут получить, равно от 0 до N включительно.
Начните массив с инициализации 0, за исключением первой записи 1. Это описывает вероятности после того, как ни одно из штатов не было включено в расчет: они обязательно получат 0 голосов выборщиков, если штаты еще не включены.
Теперь для нового штата (скажем, Вашингтона) мы можем обновить массив, включив в него и этот штат. Допустим, есть k голосов выборщиков, и вероятность того, что наш кандидат победит, равна p.
Пусть P2
будет новым массивом вероятностей. Если i ‹ k, то:
P2[i] = P[i] * (p - 1)
А если i >= k, то:
P2[i] = P[i] * (p - 1) + P[i-k] * p
То есть вероятность того, что кандидат сейчас имеет i голосов, равна вероятности того, что у него уже было i голосов и он потерял Вашингтон, плюс вероятность того, что ранее у него было i-k голосов (если это возможно) и он выиграл Вашингтон.
Как только мы включили все подобные штаты, вероятность того, что они выиграют выборы, равна сумме вероятностей того, что они получат i голосов, где i > N/2.
В псевдокоде:
P[] = {1, 0, 0, ..., 0} // size N+1
for state of all_states {
P2 = new array of size N+1.
for i = 0, 1 ... N {
let p = state.RChance / 100.0
let k = state.ElectoralVotes
P2[i] = P[i] * (1 - p)
if i >= k {
P2[i] += P[i - k] * p
}
}
P = P2
}
win_probability = sum(P[i] for i = floor(N/2)+1 ... N)
В принципе, можно избежать массива P2
, обновив P
на месте, но это немного сложнее в кодировании (потому что вам придется выполнять итерацию в обратном направлении, чтобы избежать изменения записей, которые вам позже понадобятся для чтения). Также в принципе массив P может иметь размер floor(N/2) + 2
, причем последний элемент непосредственно представляет вероятность выигрыша. Но опять же, это еще больше усложняет кодирование.
person
Paul Hankin
schedule
15.07.2016