UVa Problem Solution: 10149 - Yahtzee


I'm stuck by this problem for two days. Finally I searched for some hints and came to this solution.
The key points to solve this problem are:
  1) using bitmap to record all the possible combinations, and
  2) using DP to handle the bonus.   

Code:
  1. /*************************************************************************
  2.  * Copyright (C) 2008 by liukaipeng                                      *
  3.  * liukaipeng at gmail dot com                                           *
  4.  *************************************************************************/
  5. /* @JUDGE_ID 00000 10149 C++ "Yahtzee" */
  6. #include <iostream>
  7. #include <fstream>
  8. #include <string>
  9. #include <vector>
  10. #include <algorithm>
  11. #include <limits>
  12. using namespace std;
  13. int const ncategories = 13;
  14. int const nrounds = 13;
  15. int const ndices = 5;
  16. int const ncombinations = 8192; /* 1 << 13 + 1 */
  17. int const nupper = 64; /* 63 + 1 */
  18. int nmapped[ncombinations];
  19. int ones(int dices[]) 
  20. {
  21.   int score = 0;
  22.   for (int i = 0; i < ndices; ++i) {
  23.     if (dices[i] == 1) {
  24.       score += 1;
  25.     }
  26.   }
  27.   return score;
  28. }
  29. int twos(int dices[]) 
  30. {
  31.   int score = 0;
  32.   for (int i = 0; i < ndices; ++i) {
  33.     if (dices[i] == 2) {
  34.       score += 2;
  35.     }
  36.   }
  37.   return score;
  38. }
  39. int threes(int dices[]) 
  40. {
  41.   int score = 0;
  42.   for (int i = 0; i < ndices; ++i) {
  43.     if (dices[i] == 3) {
  44.       score += 3;
  45.     }
  46.   }
  47.   return score;
  48. }
  49. int fours(int dices[]) 
  50. {
  51.   int score = 0;
  52.   for (int i = 0; i < ndices; ++i) {
  53.     if (dices[i] == 4) {
  54.       score += 4;
  55.     }
  56.   }
  57.   return score;
  58. }
  59. int fives(int dices[]) 
  60. {
  61.   int score = 0;
  62.   for (int i = 0; i < ndices; ++i) {
  63.     if (dices[i] == 5) {
  64.       score += 5;
  65.     }
  66.   }
  67.   return score;
  68. }
  69. int sixes(int dices[]) 
  70. {
  71.   int score = 0;
  72.   for (int i = 0; i < ndices; ++i) {
  73.     if (dices[i] == 6) {
  74.       score += 6;
  75.     }
  76.   }
  77.   return score;
  78. }
  79. int chance(int dices[]) 
  80. {
  81.   int score = 0;
  82.   for (int i = 0; i < ndices; ++i) {
  83.     score += dices[i];
  84.   }
  85.   return score;
  86. }
  87. int three_kind(int dices[]) 
  88. {
  89.   int score = 0;
  90.   if (dices[0] == dices[2] || 
  91.       dices[1] == dices[3] || 
  92.       dices[2] == dices[4]) {
  93.     for (int i = 0; i < ndices; ++i) {
  94.       score += dices[i];
  95.     }
  96.   }
  97.   return score;
  98. }
  99. int four_kind(int dices[]) 
  100. {
  101.   int score = 0;
  102.   if (dices[0] == dices[3] || 
  103.       dices[1] == dices[4]) {
  104.     for (int i = 0; i < ndices; ++i) {
  105.       score += dices[i];
  106.     }
  107.   }
  108.   return score;
  109. }
  110. int five_kind(int dices[]) 
  111. {
  112.   int score = 0;
  113.   if (dices[0] == dices[4]) {
  114.     score = 50;
  115.   }
  116.   return score;
  117. }
  118. int short_straight(int dices[]) 
  119. {
  120.   int score = 0;
  121.   if (dices[0] == dices[1]-1 && 
  122.       dices[1] == dices[2]-1 && 
  123.       dices[2] == dices[3]-1 ||
  124.       dices[1] == dices[2]-1 && 
  125.       dices[2] == dices[3]-1 && 
  126.       dices[3] == dices[4]-1) {
  127.     score = 25;
  128.   }
  129.   return score;
  130. }
  131. int long_straight(int dices[]) 
  132. {
  133.   int score = 0;
  134.   if (dices[0] == dices[1]-1 && 
  135.       dices[1] == dices[2]-1 &&
  136.       dices[2] == dices[3]-1 && 
  137.       dices[3] == dices[4]-1) {
  138.     score = 35;
  139.   }
  140.   return score;
  141. }
  142. int full_house(int dices[]) 
  143. {
  144.   int score = 0;
  145.   if (dices[0] == dices[1] && 
  146.       dices[2] == dices[4] ||
  147.       dices[0] == dices[2] && 
  148.       dices[3] == dices[4]) {
  149.     score = 40;
  150.   }
  151.   return score;
  152. }
  153.       
  154. struct mapping
  155. {
  156.   int map;
  157.   int upper;
  158. };
  159. void best_categorization(int scores[][ncategories], int categorization[], 
  160.                          int& bonus, int& score)
  161. {
  162.   int best[ncombinations][nupper];
  163.   mapping previous[ncombinations][nupper];
  164.   for (int i = 0; i < ncombinations; ++i) {
  165.     for (int j = 0; j < nupper; ++j) {
  166.       best[i][j] = numeric_limits<int>::min();
  167.     }
  168.   }
  169.   best[0][0] = 0;
  170.   for (int r = 0; r < nrounds; ++r) {
  171.     for (int c = 0; c < ncategories; ++c) {
  172.       int score = scores[r][c];
  173.       int upper = c < 6 ? score : 0;
  174.       for (int map = 0, add = 1 << c; map < ncombinations; ++map) {
  175.         if (nmapped[map] != r || map & add) continue;
  176.         for (int u = 0; u < nupper; ++u) {
  177.           int newscore = score + best[map][u];
  178.           int newupper = upper + u < nupper ? upper + u : nupper - 1;
  179.           if (newscore > best[map|add][newupper]) {
  180.             best[map|add][newupper] = newscore;
  181.             previous[map|add][newupper].map = map;
  182.             previous[map|add][newupper].upper = u;
  183.           }
  184.         }
  185.       }
  186.     }
  187.   }
  188.   int map = ncombinations - 1;
  189.   int upper = nupper - 1;
  190.   bonus = 35;
  191.   score = best[map][upper] + bonus;
  192.   for (int u = 0; u < nupper; ++u) {
  193.     if (score < best[map][u]) {
  194.       bonus = 0;
  195.       score = best[map][u];
  196.       upper = u;
  197.     }
  198.   }
  199.   
  200.   while (map) {
  201.     mapping pre = previous[map][upper];
  202.     int c = 0;
  203.     for (int add = map ^ pre.map; add >>= 1; ++c) /* NOP */;
  204.     categorization[c] = best[map][upper] - best[pre.map][pre.upper];
  205.     map = pre.map;
  206.     upper = pre.upper;
  207.   }
  208. }
  209. int main(int argc, char *argv[])
  210. {
  211. #ifndef ONLINE_JUDGE
  212.   filebuf in, out;
  213.   cin.rdbuf(in.open((string(argv[0]) + ".in").c_str(), ios_base::in));
  214.   cout.rdbuf(out.open((string(argv[0]) + ".out").c_str(), ios_base::out));
  215. #endif
  216.   
  217.   /* calculate the number of "used categories" for each combination*/
  218.   for (int i = 0; i < ncombinations; ++i) {
  219.     for (int j = 0; j < ncategories; ++j) {
  220.       nmapped[i] += (i & (1 << j)) ? 1 : 0;
  221.     }
  222.   }
  223.   typedef int (*scorer)(int []);
  224.   scorer scorers[ncategories] = { 
  225.     &ones, &twos, &threes, &fours, &fives,  &sixes, &chance, 
  226.     &three_kind, &four_kind, &five_kind, &short_straight, &long_straight, 
  227.     &full_house, 
  228.   };
  229.   
  230.   int dices[ndices];
  231.   int scores[nrounds][ncategories];
  232.   int d = 0, r = 0, g = 0;
  233.   while (cin >> dices[d++ % ndices]) {
  234.     if (d / ndices > r) {
  235.       sort(dices, dices + ndices);
  236.       for (int c = 0; c < ncategories; ++c) {
  237.         scores[r % nrounds][c] = scorers[c](dices);
  238.       }
  239.       r = d / ndices;
  240.     }
  241.     if (r / nrounds > g) {
  242.       g = r / nrounds;
  243.       int categorization[ncategories];
  244.       int bonus = 0;
  245.       int score = 0;
  246.       best_categorization(scores, categorization, bonus, score);
  247.       for (int c = 0; c < ncategories; ++c) {
  248.         cout << categorization[c] << ' ';
  249.       }
  250.       cout << bonus << ' ' << score << '/n';
  251.     }
  252.   }
  253.   return 0;
  254. }

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值