1
+ #include < iostream>
2
+ #include < iomanip>
3
+ #include < sstream>
4
+ #include < vector>
5
+ #include < algorithm>
6
+ #include < unordered_map>
7
+ #include < unordered_set>
8
+ using namespace std ;
9
+
10
+ void parse_input (
11
+ vector<int > &reactants,
12
+ vector<int > &products,
13
+ unordered_map<int , vector<vector<int >>> &reactions) {
14
+
15
+ int n, m, k;
16
+ cin >> n;
17
+ reactants.resize (n);
18
+ for (int i = 0 ; i < n; ++i) cin >> reactants[i];
19
+
20
+ cin >> m;
21
+ products.resize (m);
22
+ // store products in reverse order, to reduce the time of vector::pop_back when searching
23
+ for (int i = 0 ; i < m; ++i) cin >> products[m-i-1 ];
24
+
25
+ cin >> k;
26
+ string line;
27
+ getline (cin, line); // ignore the newline character after k
28
+ unordered_set<int > ignore_self_products;
29
+ for (int i = 0 ; i < k; ++i) {
30
+ int reactions_product;
31
+ vector<int > reactions_reactants;
32
+
33
+ string part;
34
+ bool next_part_is_product = false ;
35
+ getline (cin, line);
36
+ stringstream ss (line);
37
+ // split the line by space, get reactants and product, store in reactions
38
+ while (getline (ss, part, ' ' )) {
39
+ if (part == " +" ) continue ;
40
+ else if (part == " ->" ) { next_part_is_product = true ; continue ; }
41
+
42
+ if (next_part_is_product) reactions_product = stoi (part);
43
+ else reactions_reactants.push_back (stoi (part));
44
+ }
45
+
46
+ // check if the product is the same as the reactants
47
+ reactions[reactions_product].push_back (reactions_reactants);
48
+ if (reactions_reactants.size () == 1 && *reactions_reactants.begin () == reactions_product)
49
+ ignore_self_products.insert (reactions_product);
50
+ }
51
+
52
+ // fill in self reactions if not exist
53
+ for (int i = 0 ; i < m; i++) {
54
+ int product = products[i];
55
+ if (ignore_self_products.find (product) != ignore_self_products.end ()) continue ;
56
+ reactions[product].push_back (vector<int >{ product });
57
+ }
58
+ }
59
+
60
+ // backtracking search
61
+ void search (
62
+ vector<int > &remain_products,
63
+ unordered_set<int > &remain_reactants,
64
+ unordered_map<int , vector<vector<int >>> &reactions,
65
+ vector<pair<int , vector<int >>> &solution,
66
+ bool &is_found) {
67
+
68
+ // if found solution, stop searching
69
+ if (is_found) return ;
70
+
71
+ // if no more products remain, got a solution, set is_found flag
72
+ if (remain_products.empty ()) {
73
+ is_found = true ;
74
+ return ;
75
+ }
76
+
77
+ int product = remain_products.back ();
78
+ for (auto &reactant_set : reactions[product]) {
79
+ // validation check if the reactants are all in remain_reactants
80
+ bool is_valid_reaction = true ;
81
+ for (auto &reactant : reactant_set) {
82
+ if (remain_reactants.find (reactant) == remain_reactants.end ()) {
83
+ is_valid_reaction = false ;
84
+ break ;
85
+ }
86
+ }
87
+ if (!is_valid_reaction) continue ;
88
+
89
+ // record context
90
+ for (auto &reactant : reactant_set) remain_reactants.erase (reactant);
91
+ remain_products.pop_back ();
92
+ solution.push_back ({product, reactant_set});
93
+
94
+ // search next
95
+ search (remain_products, remain_reactants, reactions, solution, is_found);
96
+ if (is_found) return ; // check point for early stop if found solution
97
+
98
+ // back
99
+ for (auto &reactant : reactant_set) remain_reactants.insert (reactant);
100
+ remain_products.push_back (product);
101
+ solution.pop_back ();
102
+ }
103
+ }
104
+
105
+ int main () {
106
+ ios::sync_with_stdio (false );
107
+
108
+ vector<int > reactants;
109
+ vector<int > products;
110
+ unordered_map<int , vector<vector<int >>> reactions;
111
+
112
+ parse_input (reactants, products, reactions);
113
+
114
+ // sort reactions by reactants order to find the 1st solution as best solution
115
+ for (auto &reaction : reactions) {
116
+ sort (reaction.second .begin (), reaction.second .end (), [&](const vector<int > &a, const vector<int > &b) {
117
+ for (int j = 0 ; j < a.size () && j < b.size (); j++) {
118
+ if (a[j] != b[j]) return a[j] < b[j];
119
+ }
120
+ });
121
+ }
122
+
123
+ auto r = unordered_set<int >(reactants.begin (), reactants.end ());
124
+ vector<pair<int , vector<int >>> solution;
125
+ bool is_find = false ;
126
+ search (products, r, reactions, solution, is_find);
127
+
128
+ for (auto &s : solution) {
129
+ cout << setfill (' 0' ) << setw (2 ) << s.second [0 ];
130
+ for (int i = 1 ; i < s.second .size (); i++) cout << " + " << setfill (' 0' ) << setw (2 ) << s.second [i];
131
+ cout << " -> " << setfill (' 0' ) << setw (2 ) << s.first << endl;
132
+ }
133
+
134
+ return 0 ;
135
+ }
0 commit comments