UVA129 暴力dfs,有许多值得学习的代码
紫书195
题目大意:给一个困难的串,困难的串的定义就是里面没有重复的串。
思路:不需要重新对之前的串进行判重,只需要对当前的加入的字符进行改变即可。
因为是判断字典序第k个的字符串,所以要多一个全局变量cnt来记录目前是第几次循环到了。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int maxn = 1000000 + 5; 5 int n, L; 6 int s[maxn]; 7 int cnt; 8 9 bool dfs(int cur){ 10 //printf("cur = %d\n", cur); 11 if (cnt++ == n){ 12 for (int i = 0; i < cur; i++){ 13 if (i % 64 == 0 && i > 0) printf("\n"); 14 else if (i % 4 == 0 && i > 0) printf(" "); 15 printf("%c", s[i] + 'A'); 16 17 } 18 printf("\n"); 19 printf("%d\n", cur); 20 return 0; 21 } 22 else { 23 for (int i = 0; i < L; i++){ 24 s[cur] = i; 25 bool flag = true; 26 /*下面的这个暴力枚举半长的一定要学会*/ 27 for (int j = 1; j * 2 <= cur + 1; j++){/*必须cur+1,因为cur是从第0位开始的*/ 28 int equa = 1; 29 for (int k = 0; k < j; k++){ 30 if (s[cur - k] != s[cur - j - k]){ 31 equa = 0; 32 break; 33 } 34 } 35 if (equa == 1) {flag = false; break;} 36 } 37 if (flag){ 38 if (!dfs(cur + 1)) return false; 39 } 40 } 41 } 42 return 1; 43 } 44 45 int main(){ 46 while (scanf("%d%d", &n, &L) && n + L != 0){ 47 cnt = 0; 48 dfs(0); 49 } 50 return 0; 51 }
关键:暴力dfs法不需要对之前已经确定的状态再次进行条件确定。 二分寻找合法串。 全局记录字典序的序列。
并且懂得暴力枚举一般的技巧
定义!!!!很重要。
目前如果我们放入的这个串合法的,那么二分j,那么对于cur-j和cur-j-k也必须要是合法的才行,所以这个是判断的条件,也是新手入门的难点