基本的dfs搜索一般都是直接从一个点出发,再从这个点到下一个
但是这题使用了另一种思路的dfs
每次选择点不是根据上一个点来推进,而是从整个地图中选择没有选过的点
也就是扫描一遍地图,从中选择还没有使用过的点,这种方式往往用于两个点之间的转移规则比较复杂的情况,比如这题,每次需要使用两个点,而不是一个,同时有横竖两种方向。
使用这种方式时需要注意在找到第一个点之后需要立即return。
#include <bits/stdc++.h> #include <hash_map> #include <hash_set> using namespace std; using namespace __gnu_cxx; //#pragma GCC optimize(2) #define n 3 #define m 10 int Map[3][10]; bool check(void) { for(int i = 0; i < n-1; i++) { for(int j = 0; j < m-1; j++) { int cc = Map[i][j]; if(Map[i+1][j] == cc && cc == Map[i][j+1] && cc == Map[i+1][j+1]) return false; } } return true; } set<string> ans; string tmp; void dfs(int count) { if(count == n*m) { tmp.clear(); char ch[3*10]; int t = 0; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { ch[t++]= (Map[i][j]+'A'); } } tmp += ch; if(check() && ! ans.count(tmp)) { ans.insert(tmp); // cout << tmp << endl; } return; } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { if(Map[i][j] == 0) { if(j+1 < m && Map[i][j+1] == 0) { Map[i][j] = 1; Map[i][j+1] = 1; dfs(count + 2); Map[i][j] = 0; Map[i][j+1] = 0; } if(j+1 < m && Map[i][j+1] == 0) { Map[i][j] = 2; Map[i][j+1] = 2; dfs(count + 2); Map[i][j] = 0; Map[i][j+1] = 0; } if(i+1 < n && Map[i+1][j] == 0) { Map[i][j] = 1; Map[i+1][j] = 1; dfs(count+2); Map[i][j] = 0; Map[i+1][j] = 0; } if(i+1 < n && Map[i+1][j] == 0) { Map[i][j] = 2; Map[i+1][j] = 2; dfs(count+2); Map[i][j] = 0; Map[i+1][j] = 0; } return ; // 注意,一定要加上,避免重复计算 } } } } #define zpl int main(int argc, char *argv[]) { #ifdef zpl freopen("F:\\data.txt", "r", stdin); #endif // zpl dfs(0); cout << ans.size() << endl; return 0; }