UVa Problem 10001 Garden of Eden (伊甸园)

// Garden of Eden (伊甸园) // PC/UVa IDs: 110806/10001, Popularity: B, Success rate: average Level: 2 // Verdict: Accepted // Submission Date: 2011-08-11 // UVa Run Time: 0.660s // // 版权所有(C)2011,邱秋。metaphysis # yeah dot net // // 该题可使用回溯法寻找给定状态的前驱,若能找到前驱,则为可达,若无法找到前驱,则为伊甸园状态。 // // 值得注意的是,网上有人使用下列解法:模拟细胞自动机的演化,判断新的状态和初始状态以及已经生成状 // 态的关系,若新生成的状态和初始状态相同,则表明初始状态可达,若新生成的状态和之前已生成的某个状 // 态相同,则表明形成了一个循环,不会再到达初始状态,判断初始状态为伊甸园状态。使用这种解法是错误 // 的,假设有一个状态 A 和演化规则 E,从初始状态 A 经过一系列状态到达状态 B,然后再经过一系列状 // 态再次到达状态 B,则使用上面的解法判断从状态 A 到状态 B 之间的那些状态时,会得出是伊甸园状态 // 的错误结论。 // // 更多信息可参考:http://mathworld.wolfram.com/ElementaryCellularAutomaton.html 。 #include <iostream> #include <vector> using namespace std; #define CODESIZE 8 bool finished; bool is_garden; // 根据当前细胞和左右两个细胞的状态获得对应的变换规则。 int indexer(int a, int b, int c) { return (a << 2) + (b << 1) + c; } void evolution(vector <int> &a, vector <int> &b, int automaton[]) { int last = a.size() - 1; b[0] = automaton[indexer(a[last], a[0], a[1])]; for (int i = 1; i < last; i++) b[i] = automaton[indexer(a[i - 1], a[i], a[i + 1])]; b[last] = automaton[indexer(a[last - 1], a[last], a[0])]; } // 比较两个状态是否相同。 bool equal(vector <int> &a, vector <int> &b) { for (int i = 0; i < a.size(); i++) if (a[i] != b[i]) return false; return true; } // 回溯寻找前驱。 void backtrack(vector <int> &ancestor, vector <int> &target, int automaton[], int current) { if (current == (ancestor.size() - 2)) { vector <int> now(ancestor.size()); evolution(ancestor, now, automaton); if (equal(now, target)) { finished = true; is_garden = false; } } else { for (int i = 0; i <= 1; i++) { int index = indexer(ancestor[current], ancestor[current + 1], i); if (automaton[index] == target[current + 1]) { ancestor[current + 2] = i; backtrack(ancestor, target, automaton, current + 1); if (finished) return; } } } } // 判断是否有前驱存在。 bool no_ancestor(vector <int> &target, int automaton[]) { int cells = target.size(); vector <int> ancestor(cells); for (int i = 0; i < CODESIZE; i++) if (automaton[i] == target[0]) { ancestor[cells - 1] = ((i & 4) >> 2); ancestor[0] = ((i & 2) >> 1); ancestor[1] = (i & 1); finished = false; is_garden = true; backtrack(ancestor, target, automaton, 0); if (is_garden == false) return false; } return true; } // 判定给定的条件是否为伊甸园状态。 bool is_garden_of_eden(int identifier, int cells, string state) { // 判断一些特殊的细胞自动机。 if (identifier == 204) return false; // 当自动机编号为 0 时,有非 0 格则为伊甸园。 if (identifier == 0) { for (int i = 0; i < state.length(); i++) if (state[i] != '0') return true; return false; } // 当自动机编号为 255 时,有非 1 格则为伊甸园。 if (identifier == 255) { for (int i = 0; i < state.length(); i++) if (state[i] != '1') return true; return false; } // 获取最初状态,自动机对应的编码变换规则。 vector <int> ancestor(cells); for (int i = 0; i < cells; i++) ancestor[i] = (state[i] - '0'); int automaton[CODESIZE]; for (int i = 0; i < CODESIZE; i++) { automaton[i] = identifier % 2; identifier /= 2; } return no_ancestor(ancestor, automaton); } int main(int ac, char *av[]) { int identifier, cells; string state; // 读入数据。 while (cin >> identifier >> cells >> state) { bool result = is_garden_of_eden(identifier, cells, state); cout << (result ? "GARDEN OF EDEN" : "REACHABLE") << endl; } return 0; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值