[关闭]
@DingCao-HJJ 2015-10-30T14:46:41.000000Z 字数 7349 阅读 1220

sicily_1151 魔板

sicily


题目

sicily_1150 简单魔板
仅仅是最大步数可以超过10.

思路

  1. 直接剪枝bfs, 然而很不幸地楼主一直MLE……
  2. 使用康托展开公式来检查一个节点是否已经遍历过。因为能够将n个无重复元素的排列映射到刚好n!个数, 所以可以大大地节省内存。

代码

  1. // Copyright (c) 2015 HuangJunjie@SYSU(SNO:13331087). All Rights Reserved.
  2. // 1151 魔板: http://soj.sysu.edu.cn/1151
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <string>
  6. #include <queue>
  7. using namespace std;
  8. struct Node {
  9. int state;
  10. string opt;
  11. };
  12. bool isvisited[40320] = { 0 };
  13. int factor[8] = { 1, 1, 2, 6, 24, 120, 720, 5040 };
  14. Node doA(const Node& node);
  15. Node doB(const Node& node);
  16. Node doC(const Node& node);
  17. int contor(Node current);
  18. int main() {
  19. int max_steps;
  20. Node aim;
  21. Node start;
  22. start.state = 12348765;
  23. start.opt = "";
  24. while (scanf("%d", &max_steps) != EOF && max_steps != -1) {
  25. int digit;
  26. aim.state = 0;
  27. for (int i = 0; i < 8; i++) {
  28. scanf("%d", &digit);
  29. aim.state *= 10;
  30. aim.state += digit;
  31. }
  32. memset(isvisited, 0, sizeof(isvisited));
  33. queue<Node> que;
  34. que.push(start);
  35. while (!que.empty()) {
  36. Node current = que.front();
  37. que.pop();
  38. if (isvisited[contor(current)] == true) continue;
  39. else
  40. isvisited[contor(current)] = true;
  41. if (current.opt.size() > max_steps) {
  42. printf("-1\n");
  43. break;
  44. }
  45. if (contor(current) == contor(aim)) {
  46. printf("%d %s\n", current.opt.size(), current.opt.c_str());
  47. break;
  48. }
  49. Node Anext = doA(current);
  50. // if (isvisited[contor(Anext)] == false)
  51. que.push(Anext);
  52. Node Bnext = doB(current);
  53. // if (isvisited[contor(Anext)] == false)
  54. que.push(Bnext);
  55. Node Cnext = doC(current);
  56. // if (isvisited[contor(Anext)] == false)
  57. que.push(Cnext);
  58. }
  59. }
  60. return 0;
  61. }
  62. Node doA(const Node& node) {
  63. Node Anext;
  64. Anext.state = node.state % 10000 * 10000 + node.state / 10000;
  65. Anext.opt = node.opt + 'A';
  66. return Anext;
  67. }
  68. Node doB(const Node& node) {
  69. Node Bnext;
  70. int up = node.state / 10000;
  71. int down = node.state % 10000;
  72. Bnext.state = (up / 10 + up % 10 * 1000) * 10000 + (down / 10 + down % 10 * 1000);
  73. Bnext.opt = node.opt + 'B';
  74. return Bnext;
  75. }
  76. Node doC(const Node& node) {
  77. Node Cnext;
  78. int fact = 10000000;
  79. int temp[8];
  80. for (int i = 0; i < 8; i++) {
  81. temp[i] = (node.state / fact) % 10;
  82. fact /= 10;
  83. }
  84. Cnext.state = (temp[0] * 1000 + temp[5] * 100 + temp[1] * 10 + temp[3]) * 10000 +
  85. (temp[4] * 1000 + temp[6] * 100 + temp[2] * 10 + temp[7]);
  86. Cnext.opt = node.opt + 'C';
  87. return Cnext;
  88. }
  89. int contor(Node current) {
  90. int fact = 10000000;
  91. int temp[8];
  92. for (int i = 0; i < 8; i++) {
  93. temp[i] = (current.state / fact) % 10;
  94. fact /= 10;
  95. }
  96. int sum = 0;
  97. for (int i = 0; i < 8; i++) {
  98. int count = 0;
  99. for (int j = i + 1; j < 8; j++) {
  100. if (temp[i] > temp[j]) count++;
  101. }
  102. sum += count*factor[7 - i];
  103. }
  104. return sum;
  105. }

优化

将已经遍历过的节点的状态存起来即可,算是小小的优化吧。

  1. // Copyright (c) 2015 HuangJunjie@SYSU(SNO:13331087). All Rights Reserved.
  2. // 1151 魔板: http://soj.sysu.edu.cn/1151
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <string>
  6. #include <queue>
  7. using namespace std;
  8. struct Node {
  9. int state;
  10. string opt;
  11. };
  12. bool isvisited[40320] = { 0 };
  13. string opts[40320]; // operation records
  14. int factor[8] = { 1, 1, 2, 6, 24, 120, 720, 5040 };
  15. Node doA(const Node& node);
  16. Node doB(const Node& node);
  17. Node doC(const Node& node);
  18. int contor(Node current);
  19. int main() {
  20. int max_steps;
  21. Node aim;
  22. Node start;
  23. start.state = 12348765;
  24. start.opt = "";
  25. while (scanf("%d", &max_steps) != EOF && max_steps != -1) {
  26. int digit;
  27. aim.state = 0;
  28. for (int i = 0; i < 8; i++) {
  29. scanf("%d", &digit);
  30. aim.state *= 10;
  31. aim.state += digit;
  32. }
  33. if (opts[contor(aim)] != "") {
  34. printf("%d %s\n", opts[contor(aim)].size(), opts[contor(aim)].c_str());
  35. continue;
  36. }
  37. memset(isvisited, 0, sizeof(isvisited));
  38. queue<Node> que;
  39. que.push(start);
  40. while (!que.empty()) {
  41. Node current = que.front();
  42. que.pop();
  43. if (isvisited[contor(current)] == true) {
  44. continue;
  45. } else {
  46. isvisited[contor(current)] = true;
  47. // stores the operation path.
  48. if (opts[contor(current)] == "")
  49. opts[contor(current)] = current.opt;
  50. }
  51. if (current.opt.size() > max_steps) {
  52. printf("-1\n");
  53. break;
  54. }
  55. if (contor(current) == contor(aim)) {
  56. printf("%d %s\n", current.opt.size(), current.opt.c_str());
  57. break;
  58. }
  59. Node Anext = doA(current);
  60. que.push(Anext);
  61. Node Bnext = doB(current);
  62. que.push(Bnext);
  63. Node Cnext = doC(current);
  64. que.push(Cnext);
  65. }
  66. }
  67. return 0;
  68. }
  69. Node doA(const Node& node) {
  70. Node Anext;
  71. Anext.state = node.state % 10000 * 10000 + node.state / 10000;
  72. Anext.opt = node.opt + 'A';
  73. return Anext;
  74. }
  75. Node doB(const Node& node) {
  76. Node Bnext;
  77. int up = node.state / 10000;
  78. int down = node.state % 10000;
  79. Bnext.state = (up / 10 + up % 10 * 1000) * 10000 + (down / 10 + down % 10 * 1000);
  80. Bnext.opt = node.opt + 'B';
  81. return Bnext;
  82. }
  83. Node doC(const Node& node) {
  84. Node Cnext;
  85. int fact = 10000000;
  86. int temp[8];
  87. for (int i = 0; i < 8; i++) {
  88. temp[i] = (node.state / fact) % 10;
  89. fact /= 10;
  90. }
  91. Cnext.state = (temp[0] * 1000 + temp[5] * 100 + temp[1] * 10 + temp[3]) * 10000 +
  92. (temp[4] * 1000 + temp[6] * 100 + temp[2] * 10 + temp[7]);
  93. Cnext.opt = node.opt + 'C';
  94. return Cnext;
  95. }
  96. int contor(Node current) {
  97. int fact = 10000000;
  98. int temp[8];
  99. for (int i = 0; i < 8; i++) {
  100. temp[i] = (current.state / fact) % 10;
  101. fact /= 10;
  102. }
  103. int sum = 0;
  104. for (int i = 0; i < 8; i++) {
  105. int count = 0;
  106. for (int j = i + 1; j < 8; j++) {
  107. if (temp[i] > temp[j]) count++;
  108. }
  109. sum += count*factor[7 - i];
  110. }
  111. return sum;
  112. }

随机样例生成

  1. // Copyright (c) 2015 HuangJunjie@SYSU(SNO:13331087). All Rights Reserved.
  2. #define ALPHA_SIZE 26
  3. #include <iostream>
  4. #include <fstream>
  5. #include <string>
  6. #include <cstring>
  7. #include <ctime>
  8. #include <cstdio>
  9. #include <string>
  10. #include <queue>
  11. #include <vector>
  12. using namespace std;
  13. struct Node {
  14. int state;
  15. string opt;
  16. } start;
  17. bool isvisited[40320] = { 0 };
  18. string opts[40320]; // operation records
  19. int factor[8] = { 1, 1, 2, 6, 24, 120, 720, 5040 };
  20. Node doA(const Node& node);
  21. Node doB(const Node& node);
  22. Node doC(const Node& node);
  23. int contor(Node current);
  24. fstream testcase;
  25. fstream answer;
  26. void init();
  27. void makeTestCase(int cases);
  28. void build();
  29. void bfs(Node aim);
  30. Node recontor(int i);
  31. int main() {
  32. init();
  33. for (int cases = 10; cases < 10000; cases *= 10) {
  34. makeTestCase(cases);
  35. }
  36. for (int cases = 50; cases < 50000; cases *= 10) {
  37. makeTestCase(cases);
  38. }
  39. return 0;
  40. }
  41. void init() {
  42. srand(time(NULL));
  43. start.state = 12348765;
  44. start.opt = "";
  45. build();
  46. }
  47. void build() {
  48. for (int i = 0; i < 40320; i++) {
  49. if (opts[i] == "") {
  50. Node aim = recontor(i);
  51. bfs(aim);
  52. }
  53. }
  54. }
  55. void bfs(Node aim) {
  56. memset(isvisited, 0, sizeof(isvisited));
  57. queue<Node> que;
  58. que.push(start);
  59. while (!que.empty()) {
  60. Node current = que.front();
  61. que.pop();
  62. if (isvisited[contor(current)] == true) {
  63. continue;
  64. } else {
  65. isvisited[contor(current)] = true;
  66. // stores the operation path.
  67. if (opts[contor(current)] == "")
  68. opts[contor(current)] = current.opt;
  69. }
  70. if (contor(current) == contor(aim)) {
  71. return;
  72. }
  73. Node Anext = doA(current);
  74. que.push(Anext);
  75. Node Bnext = doB(current);
  76. que.push(Bnext);
  77. Node Cnext = doC(current);
  78. que.push(Cnext);
  79. }
  80. }
  81. void makeTestCase(int cases) {
  82. char buf[5];
  83. sprintf(buf, "%d", cases);
  84. string cases_str = buf;
  85. string inputname = "input" + cases_str + ".txt";
  86. string answername = "answer" + cases_str + ".txt";
  87. testcase.open(inputname, ios::out);
  88. answer.open(answername, ios::out);
  89. for (int i = 0; i < cases; i++) {
  90. int steps = rand() % cases;
  91. testcase << steps << endl;
  92. int key = rand() % 40320;
  93. Node test = recontor(key);
  94. for (int factor = 10000000; factor; factor /= 10) {
  95. if (factor != 10000000 && factor != 1000) testcase << " ";
  96. if (factor == 1000) testcase << endl;
  97. testcase << test.state / factor;
  98. test.state %= factor;
  99. }
  100. testcase << endl;
  101. answer << opts[key].size() << " " << opts[key] << endl;
  102. }
  103. testcase << -1 << endl;
  104. testcase.close();
  105. answer.close();
  106. }
  107. Node doA(const Node& node) {
  108. Node Anext;
  109. Anext.state = node.state % 10000 * 10000 + node.state / 10000;
  110. Anext.opt = node.opt + 'A';
  111. return Anext;
  112. }
  113. Node doB(const Node& node) {
  114. Node Bnext;
  115. int up = node.state / 10000;
  116. int down = node.state % 10000;
  117. Bnext.state = (up / 10 + up % 10 * 1000) * 10000 + (down / 10 + down % 10 * 1000);
  118. Bnext.opt = node.opt + 'B';
  119. return Bnext;
  120. }
  121. Node doC(const Node& node) {
  122. Node Cnext;
  123. int fact = 10000000;
  124. int temp[8];
  125. for (int i = 0; i < 8; i++) {
  126. temp[i] = (node.state / fact) % 10;
  127. fact /= 10;
  128. }
  129. Cnext.state = (temp[0] * 1000 + temp[5] * 100 + temp[1] * 10 + temp[3]) * 10000 +
  130. (temp[4] * 1000 + temp[6] * 100 + temp[2] * 10 + temp[7]);
  131. Cnext.opt = node.opt + 'C';
  132. return Cnext;
  133. }
  134. int contor(Node current) {
  135. int fact = 10000000;
  136. int temp[8];
  137. for (int i = 0; i < 8; i++) {
  138. temp[i] = (current.state / fact) % 10;
  139. fact /= 10;
  140. }
  141. int sum = 0;
  142. for (int i = 0; i < 8; i++) {
  143. int count = 0;
  144. for (int j = i + 1; j < 8; j++) {
  145. if (temp[i] > temp[j]) count++;
  146. }
  147. sum += count*factor[7 - i];
  148. }
  149. return sum;
  150. }
  151. Node recontor(int key) {
  152. Node result;
  153. result.state = 0;
  154. bool num[8] = { 0 };
  155. for (int i = 7; i >= 0; i--) {
  156. int count = -1;
  157. int remain = key / factor[i];
  158. key %= factor[i];
  159. for (int j = 0; j < 8; j++) {
  160. if (num[j] == false) count++;
  161. if (count == remain) {
  162. num[j] = true;
  163. result.state *= 10;
  164. result.state += j + 1;
  165. break;
  166. }
  167. }
  168. }
  169. return result;
  170. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注