Great thanks to:
孟海
难点不在算法,在题意。
题目给一个字符串,然后求是否有一个字符串能够通过题目所给的自动机规则变换过来,如果存在,则输出REACHABLE,否则输出GARDEN OF EDEN,就是寓意始祖,即这个字符串无法通过所给的自动及变换规则变换过来。
Left | Cell | Right | New State | Weight |
---|---|---|---|---|
[i − 1] | [i] | [i + 1] | ||
0 | 0 | 0 | 0 | 0 * 2^0 |
0 | 0 | 1 | 1 | 1 * 2^1 |
0 | 1 | 0 | 0 | 0 * 2^2 |
0 | 1 | 1 | 1 | 1 * 2^3 |
1 | 0 | 0 | 1 | 1 * 2^4 |
1 | 0 | 1 | 0 | 0 * 2^5 |
1 | 1 | 0 | 1 | 1 * 2^6 |
1 | 1 | 1 | 0 | 0 * 2^7 |
90 |
这里给的自动机规则就是当字符串中的一个字符左边右边以及它自身都满足自动机规则中的left,cell以及right的时候它自己就可以变成new state的值,然后值得注意的是,每一次父串推子串的时候都是一次性把所有推完,而不是从左往右一个一个推推一个产生一个新的字符串再继续往下推,我一开始就这么理解的所以以为题目就是问给一个串能不能推到一个和自己一样的字符串,后来经过海神指导,才明白这个题目得用子串逆推父串。下面给个具体的逆推过程:
如样例输入的第二个
204 5 10101
其自动机规则如下:
Left | Cell | Right | New State | Weight |
---|---|---|---|---|
[i − 1] | [i] | [i + 1] | ||
0 | 0 | 0 | 0 | 0 * 2^0 |
0 | 0 | 1 | 0 | 0 * 2^1 |
0 | 1 | 0 | 1 | 1 * 2^2 |
0 | 1 | 1 | 1 | 1 * 2^3 |
1 | 0 | 0 | 0 | 0 * 2^4 |
1 | 0 | 1 | 0 | 0 * 2^5 |
1 | 1 | 0 | 1 | 1 * 2^6 |
1 | 1 | 1 | 1 | 1 * 2^7 |
204 |
给出的子串是10101,第一个字符是1,由规则可知,1可以由111,110,011或者001产生:
假设是由110产生,那么所求父串的前两个和最后一个就先假设分别1,0和1
The actual arrangement of the cells will be along a circumference, so that the last cell is next to
the first.
意思是第一个字符的左边是最后一个,最后一个的右边是第一个。
接下来子传第二个字符是0,已知的子串第一个第二个分别是1和0,又由规则可得第三个字符可以为1也可以为0(100->0,101->0)。。。
就这样一个一个推下去,会推出父串最后一个字符,然后这个时候父串的字符长度实际上是n+2,因为有一个最后一个字符被复制到最前端去了,这里正好给了一个机会来验证所求父串的合法性,即只要array[0] == array[n],array[1] == array[n+1]就可以说明所求父串是存在的,也就是REACHABLE,否则就是GARDEN OF EDEN,剩下来的就是简单的回溯了。
P.S:期间因为有一个for循环的8写成了7直接导致我兽性大发神志不清地暴力提交了N次也是醉的不行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
/******************************************************** * File Name: uvaoj10001.cpp * Author: razrLeLe * Mail: razrlele@gmail.com * Homepage: https://yueyu.io * Created Time: Tue 17 Mar 2015 04:29:28 PM CST ******************************************************/ #include "vector" #include "set" #include "deque" #include "queue" #include "algorithm" #include "functional" #include "iostream" #include "cstdio" #include "cmath" #include "cstdlib" #include "string" #include "cstring" #include "string.h" #include "map" #include "cctype" #include "list" #include "stack" using namespace std; #define INF 0x3f3f3f3f #define LOCAL const int maxn = 40; int newstate[maxn]; int oldarray[maxn], newarray[maxn]; char str[maxn]; int rule, len; bool reachable; int automaton[8][3] = { {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1} }; void get_Rule(int u) { for(int i = 0; i < 8; i++) { newstate[i] = u%2; u/=2; } return ; } void solve(int u) { if(u == len) { if(newarray[0] == newarray[len] && newarray[1] == newarray[len+1]) { reachable = true; } return ; } if(u == 0) { for(int i = 0; i < 8; i++) { if(newstate[i] == oldarray[u]) { newarray[u] = automaton[i][0]; newarray[u+1] = automaton[i][1]; newarray[u+2] = automaton[i][2]; solve(u+1); } } } else { for(int i = 0; i < 8; i++) { if(newstate[i] == oldarray[u]) if(automaton[i][0] == newarray[u] && automaton[i][1] == newarray[u+1]) { newarray[u+2] = automaton[i][2]; solve(u+1); } } } return ; } int main() { #ifdef LOCAL freopen("/home/razrlele/build/data.txt", "r", stdin); freopen("/home/razrlele/build/out.txt", "w", stdout); #endif while(scanf("%d%d%s", &rule, &len, str) != EOF) { get_Rule(rule); memset(newarray, 0, sizeof(newarray)); memset(oldarray, 0, sizeof(oldarray)); for(int i = 0; i < len; i++) { oldarray[i] = str[i] - '0'; } reachable = false; solve(0); if(reachable) printf("REACHABLE\n"); else printf("GARDEN OF EDEN\n"); } return 0; } |