当前位置:   article > 正文

【PAT甲级】1179 Chemical Equation(30分)[dfs,搜索与回溯,排序]_pat1179

pat1179

问题思考:

  • 题目问每种 product 的生成化学方程式,要求使用过的 reactant 不重复。而且题目给定了一些方程式,那么解空间就限定在这些方程式外加 “自反应恒等式” 了。
  • 解空间有限,自然想到可以用搜索与回溯的路子。即一旦在搜索过程中出现了重复使用某一 reactant 就可以回溯并调转搜索方向。
  • 搜索前对反应式进行 “从小到大” 的排序,确保搜索过程有序稳步进行。自定义的排序需要借助结构体实现起来方便一些。
  • 测试点2是关于反应物是否存在的,如果没判断反应物是否存在则测试点2错误。

代码实现:

  1. #include<iostream>
  2. #include<cstring>
  3. #include<vector>
  4. #include<unordered_map>
  5. #include<algorithm>
  6. using namespace std;
  7. struct Equation {
  8. vector<int> e;
  9. bool operator < (const Equation &x) {
  10. int n = e.size(), m = x.e.size();
  11. for (int i = 0; i < n && i < m; i++) {
  12. if (e[i] != x.e[i]) return e[i] < x.e[i];
  13. }
  14. }
  15. };
  16. int n, m, k, flag, f[100], r[100], isExit[100]; // flag标记是否找到solution;f数组标记当前prod用到哪一个equation了;r数组标记当前reactant使用的次数;isExit数组用来判断equation中的reactant是否存在
  17. vector<int> reac, prod;
  18. unordered_map<int, vector<Equation>> equa;
  19. // 初始化
  20. void init() {
  21. // cin
  22. scanf("%d", &n);
  23. for (int i = 0, r; i < n; i++) {
  24. scanf("%d", &r);
  25. reac.push_back(r);
  26. isExit[r] = 1;
  27. }
  28. scanf("%d", &m);
  29. for (int i = 0, p; i < m; i++) {
  30. scanf("%d", &p);
  31. prod.push_back(p);
  32. }
  33. scanf("%d", &k);
  34. getchar();
  35. for (int i = 0; i < k; i++) {
  36. // get a line
  37. string equation;
  38. getline(cin, equation);
  39. // Parse equation
  40. int arrowPos = equation.find("->");
  41. string productPart = equation.substr(arrowPos + 3);
  42. string reactantPart = equation.substr(0, arrowPos);
  43. // classify equations into different product
  44. int product = stoi(productPart);
  45. Equation tmp;
  46. for (int j = 0; j < reactantPart.size(); j += 5) {
  47. tmp.e.push_back(stoi(reactantPart.substr(j, 2)));
  48. }
  49. equa[product].push_back(tmp);
  50. }
  51. // sort
  52. for (auto x : prod) {
  53. // don't forget to add the "self reaction"
  54. if (find(reac.begin(), reac.end(), x) != reac.end()) {
  55. equa[x].push_back(Equation{vector<int>({x})});
  56. }
  57. sort(equa[x].begin(), equa[x].end());
  58. }
  59. return ;
  60. }
  61. // 搜索解空间
  62. void dfs(int cnt) {
  63. if (cnt == m) {
  64. for (auto it : reac) {
  65. if (r[it] > 1) return ;
  66. }
  67. flag = 1;
  68. return ;
  69. }
  70. for (int i = 0; i < equa[prod[cnt]].size(); i++) {
  71. if (flag == 1) return ;
  72. f[prod[cnt]] = i;
  73. // 剪枝优化
  74. int flag1 = 0;
  75. for (auto it : equa[prod[cnt]][i].e) {
  76. if (r[it] > 1) return;
  77. if (!isExit[it]) flag1 = 1;
  78. }
  79. if (flag1) continue;
  80. // 搜索与回溯
  81. for (auto it : equa[prod[cnt]][i].e) r[it] += 1;
  82. dfs(cnt + 1);
  83. for (auto it : equa[prod[cnt]][i].e) r[it] -= 1;
  84. }
  85. return ;
  86. }
  87. // 输出结果
  88. void output() {
  89. for (int i = 0; i < m; i++) {
  90. int p = prod[i];
  91. vector<int> e = equa[p][f[p]].e;
  92. if (e.size() == 1 && e[0] == p) {
  93. printf("%02d -> %02d\n", p, p);
  94. } else {
  95. for (int j = 0; j < e.size(); j++) {
  96. j && printf(" + ");
  97. printf("%02d", e[j]);
  98. }
  99. printf(" -> %02d\n", p);
  100. }
  101. }
  102. return ;
  103. }
  104. int main() {
  105. init();
  106. dfs(0);
  107. output();
  108. return 0;
  109. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/189506
推荐阅读
相关标签
  

闽ICP备14008679号