E - Red Polyomino
题意:
给定一个
n
×
n
n\times n
n×n 的格子,
′
#
′
'\#'
′#′ 代表黑色,
′
.
′
'.'
′.′ 代表白色
我们每次选出
k
k
k 个白色的格子并涂成红色,并且红色格子必须是连通的(上下左右移动可以从任意一个红色格子到另外一个红色格子),求有多少种染色方案
思路:
D
F
S
DFS
DFS
方案去重的思路比较妙
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 4e2 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
char mp[10][10];
ll ans = 0;
void dfs(int cnt){
if(cnt == 0){
++ans;return;
}
vector <pair<int,int> > v;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j){
if(mp[i][j] == '.'){
bool f = 0;
for(int k = 0; k < 4; ++k){//找出是否存在红色格子可以到(i,j)
int xx = i + dx[k], yy = j + dy[k];
if(xx < 1 || yy < 1 || xx > n || yy > n) continue;
if(mp[xx][yy] == '@') {
f = 1;break;
}
}
if(f){// 白色格子(i,j)四周存在红色格子
mp[i][j] = '@';
dfs(cnt - 1);
mp[i][j] = '#';
v.push_back({i, j});
}
}
}
for(auto d : v) mp[d.first][d.second] = '.';
}
void work()
{
cin >> n >> m;
for(int i = 1; i <= n; ++i) cin >> (mp[i] + 1);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j){
if(mp[i][j] == '.'){
mp[i][j] = '@';// 涂成红色
dfs(m - 1);// 还需要选m-1个
mp[i][j] = '#';// 包含(i,j)格子的染色方案都求出来了,染成黑色防止后边再次选中(i,j)
}
}
cout << ans;
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}