基本的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;
}