这题主要是采用其他搜索顺序,我们平时是像洪水填充那样搜完一个连通块,但这个不行,我们可以采用每次都找整副图的方法,每次找一个点,然后判这个点是否连通就可以了。这样凑满五个点,重复的话我们可以使用状态压缩判重,就这样就可以写dfs了。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<sstream>
#include<queue>
#include<list>
#include<bitset>
#include<stack>
#include<bitset>
#include<iomanip>
#include<set>
#include<cmath>
#include<map>
#include<functional>
#define int long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define _BYTE unsigned char
#define HIBYTE(x) (*((_BYTE*)&(x)+1))
#define eps 1e-8
//#define double long double
using namespace std;
int n,k,ans;
bool vis[10][10];
char s[10][10];
map<__int128,int>mp;
const int dx[10]={0,1,-1,0,0};
const int dy[10]={0,0,0,1,-1};
void getpos(int num,int &x,int &y)
{
num--;
x=num/n+1;
y=num%n+1;
}
void dfs(int now,__int128 state)
{
if(now==k)
{
ans++;
return;
}
for(int i=1;i<=n*n;i++)
{
int x,y;
getpos(i,x,y);
if(s[x][y]=='#')continue;
if(vis[x][y])continue;
bool flag=false;
for(int i=1;i<=4;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(nx>n||nx<1||ny<1||ny>n||s[nx][ny]=='#')continue;
if(vis[nx][ny])flag=true;
}
if(flag||now==0)
{
__int128 newstate=state;
newstate|=(__int128)1<<i;
if(mp[newstate])continue;
mp[newstate]++;
vis[x][y]=true;
dfs(now+1,newstate);
vis[x][y]=false;
}
}
}
signed main()
{
IO;
cin>>n;
cin>>k;
for(int i=1;i<=n;i++)
{
cin>>s[i]+1;
}
dfs(0,0);
cout<<ans;
}