#include #include using namespace std; // 0 = 1's, up through 12 = yahtzee int Category_Score(const vector& dice, int category){ vector counts(7,0); // The # of 1's through 6's int sum = 0; // we'll need this for a few things for(int i = 0; i < dice.size(); i++){ sum = sum + dice[i]; counts[dice[i]]++; } if(category < 6)// counts of a specific number return (category+1)* counts[category+1]; if(category == 6){ // 3 of a kind for(int i = 1; i <=6; i++) if(counts[i] >=3) return sum; // if we get here.. return 0; } if(category == 7){ // 4 of a kind for(int i = 1; i <=6; i++) if(counts[i] >=4) return sum; return 0; } if(category == 8){ // full house for(int i = 1; i <= 6; i++){ for(int j = 1; j <=6; j++){ if(i != j && counts[i] == 3 && counts[j] == 2) return 25; } } return 0; } if(category == 9){ // small straight- only 3 possibilities if((counts[1] > 0 && counts[2] > 0 && counts[3] > 0 && counts[4] > 0) || (counts[2] > 0 && counts[3] > 0 && counts[4] > 0 && counts[5] > 0) || (counts[3] > 0 && counts[4] > 0 && counts[5] > 0 && counts[6] > 0)) return 30; else return 0; } if(category == 10){ // large straight- only 2 possibilities if((counts[1] == 1 && counts[2] == 1 && counts[3] == 1 && counts[4] == 1 && counts[5] == 1) || (counts[2] == 1 && counts[3] == 1 && counts[4] == 1 && counts[5] == 1 && counts[6] == 1)) return 40; else return 0; } if(category == 11) // chance return sum; if(category == 12){ for(int i = 0; i <=6; i++) if(counts[i] == 5) return 50; return 0; } } void Sort(vector& v){ for(int i = 0; i < v.size(); i++) for(int j = 0; j < v.size()-1; j++){ if(v[j] > v[j+1]){ int temp = v[j]; v[j] = v[j+1]; v[j+1] = temp; } } } // returns the "compressed" version of locking the dice. "which_combo" is treated as a binary // number telling us which dice to lock int Locked_Combo(vector& dice, int which_combo){ int result = 0; Sort(dice); int factor = 16; int pos = 4; while(factor > 0){ if(which_combo > factor){ which_combo = which_combo - factor; result = result*10+dice[pos]; } factor = factor/2; pos--; } return result; } int Play(const vector& rolls, vector > > >& Memo, int category, int num_reroll, int next_die, int locked_dice){ if(category >= 13) return 0; if(next_die >= rolls.size()) return -2; if(Memo[category][num_reroll][next_die][locked_dice] != -1) return Memo[category][num_reroll][next_die][locked_dice]; int cur_next_die = next_die; vector dice(5); if(num_reroll == 0){ // new category, get 5 dice if(next_die+4 >= rolls.size()) // check for out of dice return -2; for(int i = 0; i < 5; i++){ dice[i] = rolls[next_die+i]; } cur_next_die = next_die + 5; } else{ // reroll what's left int i = 0; int temp = locked_dice; while(temp > 0){ dice[i] = temp%10; i++; temp = temp/10; } while(i < 5){ if(cur_next_die >= rolls.size()) // check for out of dice return -2; dice[i] = rolls[cur_next_die]; cur_next_die++; i++; } } int cur_score = Category_Score(dice, category); // score if we don't reroll any more int rest_score = Play(rolls, Memo, category+1, 0, cur_next_die, 0); int best_score; if(rest_score < 0) best_score = -2; else best_score = cur_score + rest_score; if(num_reroll < 2){ // then we can reroll some dice for(int i = 0; i < 32; i++){ // all combos of dice int new_locked = Locked_Combo(dice, i); int new_score = Play(rolls, Memo, category, num_reroll+1, cur_next_die, new_locked); if(new_score > 0 && new_score > best_score) best_score = new_score; } } Memo[category][num_reroll][next_die][locked_dice] = best_score; return best_score; } void Print_Dice(const vector& dice){ for(int i = 0; i < dice.size(); i++) cout << dice[i] << " "; cout << endl; } int main(){ int num_dice; cin >> num_dice; vector rolls(num_dice); for(int i = 0; i < num_dice; i++) cin >> rolls[i]; int max_score; vector > > > Memo; // 4 dimensions: category we're on, # of rerolls we've done, die # we're on, // locked die values Memo.resize(13); // 13 categories for(int i = 0; i < 13; i++){ Memo[i].resize(3); // 0-2 rerolls for(int j = 0; j < 3; j++){ Memo[i][j].resize(rolls.size()); // the position in the rolls vector for(int k = 0; k < rolls.size(); k++){ Memo[i][j][k].resize(6667, -1); // biggest locked dice can be 4 sixes } } } max_score = Play(rolls, Memo, 0, 0, 0, 0); cout << max_score << endl; return 0; }