1. 程式人生 > >10001 Garden of Eden (回溯)

10001 Garden of Eden (回溯)

Cellular automata are mathematical idealizations of physical systems in which both space and time are discrete, and the physical quantities take on a finite set of discrete values. A cellular automaton consists of a lattice (or array), usually infinite, of discrete-valued variables. The state of such automaton is completely specified by the values of the variables at each place in the lattice. Cellular automata evolve in discrete time steps, with the value at each place (cell) being affected by the values of variables at sites in its neighborhood on the previous time step. For each automaton there is a set of rules that define its evolution.

For most cellular automata there are configurations (states) that are unreachable: no state will produce them by the application of the evolution rules. These states are called Gardens of Eden for they can only appear as initial states. As an example consider a trivial set of rules that evolve every cell into 0; for this automaton any state with non-zero cells is a Garden of Eden.

In general, finding the ancestor of a given state (or the non-existence of such ancestor) is a very hard, compute intensive, problem. For the sake of simplicity we will restrict the problem to 1-dimensional binary finite cellular automata. This is, the number of cells is a finite number, the cells are arranged in a linear fashion and their state will be either 0 or 1. To further simplify the problem each cell state will depend only on its previous state and that of its immediate neighbors (the one to the left and the one to the right).

The actual arrangement of the cells will be along a circumference, so that the last cell is next to the first.

Given a circular binary cellular automaton you must find out whether a given state is a Garden of Eden or a reachable state. The cellular automaton will be described in terms of its evolution rules. For example, the table below shows the evolution rules for the automaton: Cell=XOR(Left,Right).
Left Cell Right New
[i-1] [i] [i + 1] State
0 0 0 0 0 * 20
 0 0 1 1 1 * 21
0 1 0 0 0 * 22
0 1 1 1 1 * 23
1 0 0 1 1 * 24
1 0 1 0 0 * 25
1 1 0 1 1 * 26
1 1 1 0 0 * 27
90 = Automaton Identifier


Notice that, with the restrictions imposed to this problem, there are only 256 different automata. An identifier for each automaton can be generated by taking the New State vector and interpreting it as a binary number (as shown in the table). For instance, the automaton in the table has identifier 90. The Identity automaton (every state evolves to itself) has identifier 204.

Input 

The input will consist of several test cases. Each input case will describe, in a single line, a cellular automaton and a state. The first item in the line will be the identifier of the cellular automaton you must work with. The second item in the line will be a positive integer N ( $4 \le N \le 32$) indicating the number of cells for this test case. Finally, the third item in the line will be a state represented by a string of exactly N zeros and ones. Your program must keep reading lines until the end of the input (end of file). If an input case describes a Garden of Eden you must output the string GARDEN OF EDEN. If the input does not describe a Garden of Eden (it is a reachable state) you must output the string REACHABLE.

The output for each test case must be in a different line.

0 4 1111
204 5 10101
255 6 000000
154 16 1000000000000000
GARDEN OF EDEN
REACHABLE
GARDEN OF EDEN
GARDEN OF EDEN

題目解析:

我不知道,為理解這題腦細胞耗死了多少?看了網路上的題解都未能明白題意,為了能讓大家明白我這題,儘量描述的通俗易懂。

我想分幾個部分來說明問題。

(1)目的:

有256中自動機。

題目給出的3個變數分別是:自動機的種類,新字串的長度,新字串。

問新字串是否可以,按照自動機的規則,由其他的舊字串轉化而來,

可以的話輸出REACHABLE,否則輸出GARDEN OF EDEN。

(2)規則:

Left Cell Right New
[i-1] [i] [i + 1] State
0 0 0 0 0 * 20
 0 0 1 1 1 * 21
0 1 0 0 0 * 22
0 1 1 1 1 * 23
1 0 0 1 1 * 24
1 0 1 0 0 * 25
1 1 0 1 1 * 26
1 1 1 0 0 * 27
90 = Automaton Identifier

請看上面的表格,

左邊3列:原字串當前格子(Cell)以及左右兩邊的格子的狀態,

第4列:當原字串某一段連續的3個格子符合第4列對應的左邊3列所描述的狀態時,那麼就把這3個格子中間的那個格子的值(Cell[i])轉化成New State的值。

由於左邊這3列描述了所有可能的情況,所以對任意一個字串,總可以通過這個自動機描述的法則轉化成一個新字串。

上面的話什麼意思呢?

對於編譯方式

例如:

自動機編號是 8 ,將8轉化為2進位制是00001000,每行的都對應8的一個2進位制碼
其意思為:
0 0 0 -->0
0 0 1 -->0
0 1 0 -->0
0 1 1 -->0

1 0 0 -->1

1 0 1 -->0

1 1 0 -->0

1 1 1 -->0

然後題目要求就是問給出的字串,在這種轉化機制下,能否由其他串轉化來。

(3)實現步驟

現在我按照上面表,自動機90 的規則 , 將新串 10101 逆推出舊串。

逆推的規則見上圖

 0 0 1 -> 1 

新串:      1 0 1 0 1

舊串:   0 0 1

 0 1 0 - > 0

新串:      1 0 1 0 1

舊串:   0 0 1 0

1 0 1 -> 0 

新串:      1 0 1 0 1

舊串:   0 0 1 0 1

0 1 0 -> 0

新串:      1 0 1 0 1

舊串:   0 0 1 0 1 0

1 0 0 -> 1

新串:      1 0 1 0 1

舊串:   0 0 1 0 1 0 0

由前面兩個位置推出後面一個位置,讀者可以自行推導一下,上面是新串逆推出舊串的過程。

再看這句話。

The actual arrangement of the cells will be along a circumference, so that the last cell is next to the first.

細胞將沿著圓周,使得最後一個細胞與第一個相連。

還記得我們是怎麼推匯出第一個位置的嗎?新串前兩個位置的兩個字元,是由最後兩個位置的字元來決定的。換句話說,如果能生成一個環,那就要滿足後面兩個和前面兩個相同,才能能構成環,那麼輸出REACHABLE,否則輸出GARDEN OF EDEN。

可能讀者還有一個疑惑,為什麼編號為204的自動機是一個every state evolves to itself?

因為204的編碼自動機編碼為00110011,任何2進位制的字串,經過204號規則,推出的都是它自己本身,如果不信的話,讀者可以自行推導。

AC程式碼:

#include <stdio.h>
#include <string.h>
const int N = 40;
int n;
int vis[N],state[N],newStr[N];//vis陣列表示舊的字串
bool ok;
int dir[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 dfs(int cur) {  //cur表示當前newStr的下標
	if( cur == n) {
		if( vis[0] == vis[n] && vis[1] == vis[n+1]) { //如果能構成環,則符合題意
			ok = true;
		}
		return ;
	}
	for(int i = 0; i < 8; i++) { //查詢8種編碼
		if( state[i] == newStr[cur]) { //找到與當前newStr相同的state編碼
			if(!cur) { //如果是首個位置,則vis的值可以任意取與其對應的
				vis[cur] = dir[i][0];
				vis[cur+1] = dir[i][1];
				vis[cur+2] = dir[i][2];
				dfs(cur+1);
			}
			else if(vis[cur] == dir[i][0]&& vis[cur+1] == dir[i][1]) {
				vis[cur+2] = dir[i][2];
				dfs(cur+1);
			}
		}
	}
}
int main() {
	char str[N];
	int k;
	while( scanf("%d%d%s",&k,&n,str) != EOF) {
		memset(vis,0,sizeof(vis));
		memset(state,0,sizeof(state));
		memset(newStr,0,sizeof(newStr));
		ok = false;
		for(int i = 0; i < 8; i++) { //求出每行對應的2進位制編碼
			state[i] = k % 2;
			k /= 2;
		}
		for(int i = 0; i < n; i++) {
			newStr[i] = str[i] - '0';
		}
		dfs(0);
		if( ok ) {
			printf("REACHABLE\n");
		}
		else {
			printf("GARDEN OF EDEN\n");
		}
	}
	return 0;
}