Я реализовывал рекурсивную функцию с запоминанием для ускорения. Суть программы в следующем:
Я перемешиваю колоду карт (с равным количеством красных и черных карт) и начинаю сдавать их лицевой стороной вверх. После любой карты вы можете сказать «стоп», после чего я плачу вам 1 доллар за каждую сданную красную карту, а вы платите мне 1 доллар за каждую сданную черную карту. Какова ваша оптимальная стратегия и сколько вы готовы заплатить за эту игру?
Моя рекурсивная функция выглядит следующим образом:
double Game::Value_of_game(double number_of_red_cards, double number_of_black_cards)
{
double value, key;
if(number_of_red_cards == 0)
{
Card_values.insert(Card_values.begin(), pair<double, double> (Key_hash_table(number_of_red_cards, number_of_black_cards), number_of_black_cards));
return number_of_black_cards;
}
else if(number_of_black_cards == 0)
{
Card_values.insert(Card_values.begin(), pair<double, double> (Key_hash_table(number_of_red_cards, number_of_black_cards), 0));
return 0;
}
card_iter = Card_values.find(Key_hash_table(number_of_red_cards, number_of_black_cards));
if(card_iter != Card_values.end())
{
cout << endl << "Debug: [" << number_of_red_cards << ", " << number_of_black_cards << "] and value = " << card_iter->second << endl;
return card_iter->second;
}
else
{
number_of_total_cards = number_of_red_cards + number_of_black_cards;
prob_red_card = number_of_red_cards/number_of_total_cards;
prob_black_card = number_of_black_cards/number_of_total_cards;
value = max(((prob_red_card*Value_of_game(number_of_red_cards - 1, number_of_black_cards)) +
(prob_black_card*Value_of_game(number_of_red_cards, number_of_black_cards - 1))),
(number_of_black_cards - number_of_red_cards));
cout << "Check: value = " << value << endl;
Card_values.insert(Card_values.begin(), pair<double, double> (Key_hash_table(number_of_red_cards, number_of_black_cards), value));
card_iter = Card_values.find(Key_hash_table(number_of_red_cards , number_of_black_cards ));
if(card_iter != Card_values.end());
return card_iter->second;
}
}
double Game::Key_hash_table(double number_of_red_cards, double number_of_black_cards)
{
double key = number_of_red_cards + (number_of_black_cards*91);
return key;
}
Третий оператор if — это «запоминающая» часть кода, в нем хранятся все необходимые значения. Значения, которые хранятся на карте, можно рассматривать как матрицу, эти значения будут соответствовать определенным #красным картам и #черным картам. Что действительно странно, так это то, что когда я выполняю код всего для 8 карт (4 черных и 4 красных), я получаю неверный ответ. Но когда я выполняю код для 10 карт, мой ответ неверен, но теперь мой ответ для 4 черных и 4 красных правилен (8 карт)! То же самое можно сказать и о 12 карточках, где я получаю неправильный ответ на 12 карточек, но правильный ответ на 10 карточек, и так далее, и тому подобное. В коде какая-то ошибка, но я не могу понять.
double
для хранения целых чисел? - person nneonneo   schedule 07.10.2012prob_red_card
иprob_black_card
? Они глобальны? - person nneonneo   schedule 07.10.2012double
s в качестве ключа хеш-таблицы, потому что два значения типа double могут быть фактически равны, но не хешировать одно и то же. Я не думаю, что это ваша проблема, но это проблема, которая сделает ваш мемоизатор хеш-таблиц гораздо менее полезным, чем вам хотелось бы. И сравнение их с «0», чтобы решить, должна ли рекурсия закончиться, возможно, ваша проблема. Никогда не сравнивайте двойники на равенство. - person Omnifarious   schedule 07.10.2012double
s может точно содержать целые числа размером до 50 или около того бит и не терять точность (или не сравнивать точно равные). Таким образом, безопасно помещать 32-битные целые значения вdouble
и выполнять над ними строго целочисленные операции (но, конечно, это не то, что вам следует делать). - person nneonneo   schedule 07.10.2012double
s может точно удерживать, его следует заменить обычноdouble
в большинстве систем может точно удерживать. :-) - person Omnifarious   schedule 07.10.2012