[TC SRM 665 div1 lev1] LuckySum

这道题挺有意思,转化为图来做。顶点v = (carry, zero),其中carry表示是否有从右边一位进1,zero表示是否有其中一个lucky number进入前导0。

G存储从某个顶点通过某边(取某digit)可到达的下一个顶点;E存储某顶点可出去的所有边(即该位可取的digit)。

需要特别注意corner case,当已经遍历到note的最高位,且允许前导0,且有从右边进1时,可以两个lucky number都进入前导0。

 1 class LuckySum {
 2 public:
 3     long long construct(string note) {
 4         // [carry][zero] -> digits
 5         E[0][0] = {1, 4, 8};
 6         E[0][1] = {4, 7};
 7         E[1][0] = {2, 5, 9};
 8         E[1][1] = {5, 8};
 9         // [carry][zero][digit] -> [carry][zero]
10         G[0][0][1] = {{1, 0}, {1, 1}};
11         G[0][0][4] = {{1, 0}, {1, 1}};
12         G[0][0][8] = {{0, 0}, {0, 1}};
13         G[1][0][2] = {{1, 0}, {1, 1}};
14         G[1][0][5] = {{1, 0}, {1, 1}};
15         G[1][0][9] = {{0, 0}, {0, 1}};
16         G[0][1][4] = {{0, 1}};
17         G[0][1][7] = {{0, 1}};
18         G[1][1][5] = {{0, 1}};
19         G[1][1][8] = {{0, 1}};
20         G[1][1][1] = {{0, 1}};  // corner case
21         vector<pair<bool, string>> memo(60);  // 14 * 4 + 3 + 1;
22         string sum;
23         if (!dfs(note, (int)note.size() - 1, 0, 0, memo, sum)) return -1;
24         long long res = 0;
25         for (auto c : sum) {
26             res = res * 10 + c - '0';
27         }
28         return res;
29     }
30 
31 private:
32     bool dfs(string &note, int idx, int c, int z, vector<pair<bool, string>> &memo, string &sum) {
33         if (idx < 0) {
34             sum = "";
35             return !c;
36         }
37         int key = idx << 2 | c << 1 | z;
38         if (memo[key].first) {
39             sum = memo[key].second;
40             return sum < INF;
41         }
42         sum = INF;
43         string tmp;
44         vector<int> digits = E[c][z];
45         if (idx == 0 && c && z) digits.push_back(1);  // corner case
46         for (auto d : digits) {
47             if (note[idx] != '?' && d + '0' != note[idx]) continue;
48             for (auto &s : G[c][z][d]) {
49                 if (dfs(note, idx - 1, s[0], s[1], memo, tmp)) {
50                     tmp += d + '0';
51                     if (tmp < sum) sum = tmp;
52                 }
53             }
54         }
55         memo[key].first = true;
56         memo[key].second = sum;
57         return sum < INF;
58     }
59 
60 private:
61     vector<int> E[2][2];
62     vector<vector<int>> G[2][2][10];
63     string INF = "99999999999999";
64 };

 

posted on 2017-02-19 21:31  ivancjw  阅读(228)  评论(0编辑  收藏  举报

导航