Так, новости такие. От графа пока откажемся, слишком мало кода в интернете, все почему-то выходят на матрицу смежности, что как-то не солидно. Ну, да ладно.
Удалось развить функцию, находящую вероятность завершить строку(до этого аналогичная считала вероятность собрать фантазию в топе).
Теперь функция работает с полным перебором колоды, ей не надо напрямую сообщать кол-во оставшихся карт того или иного достоинства.
Для задачи "имеем колоду, из которой последовательно(по одной) вытаскиваем М карт, каждый раз мы можем либо оставить(добавить) карту к уже имеющимся в линии, либо сбросить. Найти вероятность собрать перечень комбинаций.
Псевдокод такой.
1. Имеем линию для завершения, например
2. Определяем успешные комбинации, например
,
и т.д.
3. Для каждого шага и для каждой карты из колоды у нас 2 альтернативы: либо оставить карту, либо сбросить.
4. Введём дополнительную функцию, которая считает полную вероятность собрать комб. из п2, с колодой без карты из п3, для случаев, когда мы её добавили и когда сбросили. Она нужна для того, что если пришла
на первом подьёме(осталось ещё 3), то может быть выгоднее её сбросить, чем положить. Так как для какой-то конкретной колоды вероятность закончить стрит за оставшиеся "подьёмы" может быть ниже, чем собрать 2пары.
5. Для п.3 вызываем доп. функцию и решаем: оставлять(добавлять) карту или скидывать.
6. Повторяем п.5 для уменьшенной на 1 карту колоды
7. Выход из функции по 2 условиям: либо (какая-то)комбинация собрана, либо мы израсходовали все "подьёмы".
Доп. функция
написана с помощью рекурсии, но можно и циклами.
// FP - колво свободных "мест"
double complete_p(std::string d, std::string s, int FP)
{
std::string foo, foo2;
double t;
std::sort(s.begin(), s.end());
if(s == "45678" || s == "34567" || s == "56789" )
//|| s == "56777" || s == "56766" || s == "55567")
return 1.0;
if(s == "56777" || s == "56667" || s == "55567")
return 1.0;
// else if(s == "56677" || s == "55667" || s == "55677")
//return 1.0;
else if (s.length() == 5)
return 0.0;
if(s.length() == 4 && FP== 1) //кладём любую пришедшую карту
{
for(int i=0; i < d.size(); ++i)
{foo = s + d.at(i);
foo2 = d;
foo2.erase(foo2.begin() + i);
t = t + 1.0/(double)d.size()*complete_p(foo2,foo,FP-1);
}
return t;
}
//} while(d.size() >0);
if(s.length() == 3 && FP== 2) //кладём любую пришедшую карту
{
for(int i=0; i < d.size(); ++i)
{foo = s + d.at(i);
foo2 = d;
foo2.erase(foo2.begin() + i);
t = t + 1.0/(double)d.size()*complete_p(foo2,foo,FP-1);
}
return t;
}
};
// M - колво подьёмов по одной карте
double fill_p(std::string d, std::string s, int M)
{
std::string foo, foo2;
double t =0.0;
std::sort(s.begin(), s.end());
if(s == "45678" || s == "34567" || s == "56789" )
//|| s == "56777" || s == "56766" || s == "55567")
return 1.0;
if(s == "56777" || s == "56667" || s == "55567")
return 1.0;
//else if(s == "56677" || s == "55667" || s == "55677")
//return 1.0;
else if (s.length() == 5)
return 0.0;
//кладём или не кладём?
if (s.length() == 4 && M == 1)
{
for(int i=0; i < d.size(); ++i)
{
foo = s + d.at(i);
foo2 = d;
foo2.erase(foo2.begin() + i);
//кладём по-любому
t = t + 1.0/(double)d.size()*fill_p(foo2,foo,M-1);
}return t;
}
//тоже кладём по-любому
if (s.length() == 3 && M == 2)
{
for(int i=0; i < d.size(); ++i)
{
foo = s + d.at(i);
foo2 = d;
foo2.erase(foo2.begin() + i);
t = t + 1.0/(double)d.size()*fill_p(foo2,foo,M-1);
}return t;
}
if ( M > 2 && s.length() == 3)
{for(int i=0; i < d.size(); ++i)
{
foo = s + d.at(i);
foo2 = d;
foo2.erase(foo2.begin() + i);
if (complete_p(foo2,foo,1) >= complete_p(foo2,s,2))
t = t + 1.0/(double)d.size()*fill_p(foo2,foo,M-1);
else
t = t + 1.0/(double)d.size()*fill_p(foo2,s,M-1);
}
return t;
}
if ( M >= 2 && s.length() == 4)
{for(int i=0; i < d.size(); ++i)
{
foo = s + d.at(i);
foo2 = d;
foo2.erase(foo2.begin() + i);
if (complete_p(foo2,foo,0) >= complete_p(foo2,s,1))
t = t + 1.0/(double)d.size()*fill_p(foo2,foo,M-1);
else
t = t + 1.0/(double)d.size()*fill_p(foo2,s,M-1);
}
return t;
}
};
Перехожу к отладке подьёмов из 2 карт{можно положить 0, 1 или 2карты}
Теперь попробую скрестить ужа с ежом. А именно, так как максимизировать кол-во очков сразу для всей руки я не могу(все комбинации не перебрать), попробую минимизировать "ущерб" от (дельта ЕВочков и дельта ЕВ фантазии)
грубо говоря, в раскладе
2ка сверху снижает вер-ть фантазии(на или ) с 59% до 35%, ну, а двойка хоть и наносит "ущерб" ЕВ очкам, но не такой сокрушительный. Следовательно, если мимимизировать "суммарный ущерб", 2ка в топ идти не должна