PC/UVa:110806/10001
这题算简单的,但是不能把所有状态遍历一遍,然后变化一次,应该逆推。
以87 17 11110100000000000这个输入为例,得到的自动机表示为:
i - 1 | i | i + 1 | new |
|---|---|---|---|
| 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 0 |
为了方便,先把前一状态的头3位固定下来,根据表中可知,分别可以为000、001、010、100、100,然后根据前一状态的最末两位,以及输入状态第3位上的1,确定前一状态的第4位。重复上述步骤搜索,直到将前一状态的17位全部确定下来,最后判断发生回绕的第1位和第17位是否满足自动机。
为了编码简单,代码中通过第16和第17位的值,确定了第1位正确的值,然后再和最开始确定下来的第1位进行比较。
代码中Right是一个三维数组,表示通过当前推算出来的最末两位curr - 1和curr,得到输入状态的第curr位时,第curr + 1可能的取值范围,例如上表中,curr - 1和curr为00时,得到new = 1时,curr + 1可以是0或者1;而new = 0时,curr + 1不存在。
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#define SIZE 8
using namespace std;
void buildAutomation(int iCellular, vector<char> &vchAutomation, vector<vector<vector<char>>> &Right)
{
while (iCellular != 0){
vchAutomation.push_back((iCellular & 0x1) + '0');
iCellular >>= 1;
}
while (vchAutomation.size() != SIZE) vchAutomation.push_back('0');
for (size_t i = 0; i < vchAutomation.size(); i += 1)
{
if (vchAutomation[i] == '0'){
Right[i >> 1][0].push_back((i & 0x1) + '0');
}
else{
Right[i >> 1][1].push_back((i & 0x1) + '0');
}
}
}
void checkEden(const string &strState, size_t curr,
const vector<vector<vector<char>>> &Right, string &strPrev, bool &bPrev)
{
size_t idx = stoul(strPrev.substr(curr - 1, 2), nullptr, 2);
const vector<char> &right = Right[idx][strState[curr % strState.size()] - '0'];
if (curr == strState.size()){
if (strPrev.back() == strPrev.front()){
for (size_t i = 0; i < right.size(); i++)
{
if (right[i] == strPrev[1]){
bPrev = true;
break;
}
}
}
return;
}
if (!right.empty()){
for (size_t i = 0; i < right.size(); i++)
{
if (!bPrev){
strPrev.push_back(right[i]);
checkEden(strState, curr + 1, Right, strPrev, bPrev);
strPrev.pop_back();
}
else break;
}
}
}
int main()
{
string strLine, strState;
int iCellular, iCells;
while (getline(cin, strLine)){
istringstream iss(strLine);
iss >> iCellular >> iCells;
iss.get();
iss >> strState;
vector<char> vchAutomation;
vector<vector<vector<char>>> Right(4, vector<vector<char>>(2, vector<char>()));
buildAutomation(iCellular, vchAutomation, Right);
bool bPrev = false;
for (size_t tri = 0; tri < SIZE; tri++)
{
if (vchAutomation[tri] == strState[1]){
string strPrev;
strPrev.push_back(((tri >> 2) & 0x1) + '0');
strPrev.push_back(((tri >> 1) & 0x1) + '0');
strPrev.push_back((tri & 0x1) + '0');
checkEden(strState, 2, Right, strPrev, bPrev);
if (bPrev) break;
}
}
if (bPrev){
cout << "REACHABLE" << endl;
}
else{
cout << "GARDEN OF EDEN" << endl;
}
}
return 0;
}
/*
0 4 1111
204 5 10101
255 6 000000
154 16 1000000000000000
*/
本文深入探讨了细胞自动机理论中Eden园问题的解决方案,通过逆向推导方法,避免了全状态遍历的复杂度,提供了一种高效求解算法。以特定输入为例,详细解释了如何构建自动机并验证状态是否可达,适用于竞赛及学术研究。
229

被折叠的 条评论
为什么被折叠?



