solution-p1391
dfs
思路
这道题肯定要用DFS。如果直接暴力枚举,只有40pts。
那么,该如何优化呢?
考虑使用贪心。我们发现,当第一行确定下来时,后面几行就会受限,有唯一解!!
所以,我们只需要枚举第一行。$2^{18}$ 还是可以接受的。
总时间复杂度 $O(2^n \cdot n^2)$
代码
#include<bits/stdc++.h>
using namespace std;// 0 girl 1 boy
bool f[200][200];
int n;
int cnt2[200][200];
bool f2[200][200];//143213
int ans = 2147483647;
void print(){
for(int i = 1; i <= n; i++){
cout<<f[1][i]<<' ';
}cout<<endl;
}
void solve(int h){
int cnt = h;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(i == 1){
cnt2[i][j] = f2[i][j-1] + f2[i][j+1];
continue;
}
cnt2[i][j] = f2[i-1][j] + f2[i][j-1];
if(cnt2[i-1][j] % 2){
if(f2[i][j] == 0){
cnt++;
}
f2[i][j] = 1;
cnt2[i][j-1]++;
}else{
if(f2[i][j] == 1){
memset(cnt2, 0, sizeof(cnt2));
return ;
}
f2[i][j] = 0;
}
}
}
bool flag = true;
for(int i = 1; i <= n; i++){
if(cnt2[n][i] % 2){
flag = false;
break;
}
}
if(flag){
ans = min(ans, cnt);
}
memset(cnt2, 0, sizeof(cnt2));
}
void dfs(int x, int cnt){
if(x > n){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
f2[i][j] = f[i][j];
}
}
solve(cnt);
return ;
}
if(f[1][x] == 0){
f[1][x] = 0;
dfs(x+1, cnt);
f[1][x] = 1;
dfs(x+1, cnt+1);
f[1][x] = 0;
return ;
}else{
dfs(x+1, cnt);
}
}
int main(){
cin>>n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin>>f[i][j];
}
}
dfs(1, 0);
if(ans == 2147483647) cout<<-1<<endl;
else cout<<ans<<endl;
// cout<<ans<<endl;
return 0;
}
后续
做完这道题可以尝试一下P1764,都是一种套路的题。