《算法竞赛入门经典》这本书确实内容很丰富,但是对于初学者真的不怎么友善。主要的原因在于省略了太多的细节。为什么会有这样的情况呢?我个人是这样理解的,大多数人在给别人介绍一个知识点或者事物的时候,很容易将那些自己觉得比较简单或者基础的东西给省略掉。这种情况不是主观的,潜意识里就这么完成了。例如,我给一个人说,你看这瓶溶液是棕黄色的,至少不是硫酸铜。这里就有一个背景,硫酸铜溶液是蓝色的,我们为什么省略掉这个细节呢?因为我们潜意识里认为,别人也知道,而事实可能并非如此。回到这本书上来,有太多的内容也是专业。我最开始直接看后面的章节,真的很难看懂,又回头来逐章阅读,这种情况就好多了。
在回溯算法里7-4这一节的例题,素数环一题目就省了很多的内容。这里给出一版本可以编译运行的代码,希望可以帮到有需要的朋友。实现了两种计数方式,一种从index为0开始,一种从index为1开始。大家可以注意区别。
0基数的方案
1 #include <iostream> 2 #include <string> 3 4 #define max_num 33 5 6 int isprime[max_num]; 7 int visit[max_num]; // if a data has been visited 8 // assume that valid indices: 0,1,2,...,31, starting from 0 9 int arr[max_num]; // store the data 10 int n; 11 12 void build_isprime(int t_n) 13 { 14 if (t_n > max_num) 15 { 16 std::cout << "max_error:" << t_n << std::endl; 17 std::exit(-1); 18 } 19 // init n 20 n = t_n; 21 // init isprime 22 isprime[0] = 0; 23 isprime[1] = 0; 24 isprime[2] = 1; 25 for (int i=3;i<max_num;i++) 26 { 27 bool flag = false; 28 for (int j = 2; j < i; j++) 29 { 30 if (i % j == 0) 31 { 32 flag = true; 33 isprime[i] = 0; 34 } 35 } 36 if (!flag) 37 { 38 isprime[i] = 1; 39 } 40 } 41 // init visit and arr 42 for (int i = 0; i < max_num; i++) 43 { 44 visit[i] = 0; 45 arr[i] = 0; 46 } 47 visit[1] = 1; // number 1 has been visited, not index 1 has been visited 48 arr[0] = 1; 49 } 50 51 void dfs(int curr) 52 { 53 if (curr == n) // end condition, n is the index, not the number to deal 54 { 55 int sum_of_last_and_first = arr[0] + arr[n-1]; 56 if (isprime[sum_of_last_and_first] == 1) 57 { 58 for (int i=0;i<n;i++) 59 { 60 std::cout << arr[i] << " "; 61 } 62 std::cout << std::endl; 63 } 64 } 65 else // loop condition 66 { 67 for (int i=2;i<=n;i++) // i denotes the number we have to deal, not index 68 { 69 if (visit[i] == 0 && isprime[arr[curr-1] + i] == 1) 70 { 71 arr[curr] = i; 72 visit[i] = 1; 73 dfs(curr+1); 74 visit[i] = 0; 75 } 76 } 77 } 78 } 79 80 int main() 81 { 82 build_isprime(6); 83 dfs(1); 84 return 0; 85 }
1基数的方案
1 #include <iostream> 2 #include <string> 3 4 #define max_num 33 5 6 int isprime[max_num]; 7 int visit[max_num]; // if a data has been visited 8 // assume that valid indices: 1,2,3,...,32, starting from 1 9 int arr[max_num]; // store the data 10 int n; 11 12 void build_isprime(int t_n) 13 { 14 if (t_n > max_num) 15 { 16 std::cout << "max_error:" << t_n << std::endl; 17 std::exit(-1); 18 } 19 // init n 20 n = t_n; 21 // init isprime 22 isprime[0] = 0; 23 isprime[1] = 0; 24 isprime[2] = 1; 25 for (int i=3;i<max_num;i++) 26 { 27 bool flag = false; 28 for (int j = 2; j < i; j++) 29 { 30 if (i % j == 0) 31 { 32 flag = true; 33 isprime[i] = 0; 34 } 35 } 36 if (!flag) 37 { 38 isprime[i] = 1; 39 } 40 } 41 // init visit and arr 42 for (int i = 0; i < max_num; i++) 43 { 44 visit[i] = 0; 45 arr[i] = 0; 46 } 47 visit[1] = 1; // number 1 has been visited, not index 1 has been visited 48 arr[1] = 1; 49 } 50 51 void dfs(int curr) 52 { 53 if (curr == n+1) // end condition, n is the index, not the number to deal 54 { 55 int sum_of_last_and_first = arr[1] + arr[n]; 56 if (isprime[sum_of_last_and_first] == 1) 57 { 58 for (int i=1;i<=n;i++) 59 { 60 std::cout << arr[i] << " "; 61 } 62 std::cout << std::endl; 63 } 64 } 65 else // loop condition 66 { 67 for (int i=2;i<=n;i++) // i denotes the number we have to deal, not index 68 { 69 if (visit[i] == 0 && isprime[arr[curr-1] + i] == 1) 70 { 71 arr[curr] = i; 72 visit[i] = 1; 73 dfs(curr+1); 74 visit[i] = 0; 75 } 76 } 77 } 78 } 79 80 int main() 81 { 82 build_isprime(6); 83 dfs(2); 84 return 0; 85 }
完结。