剪格子(穷举,一维数组转二维数组,dfs判断图的连通性)
题目:
此题仍然可以套用全排列+check的模板,声明一个一维数组,以一维数组的下标代替此题的编号。数组中白色格子设置为0,粉色格子设置为1。用next_permutation可以将一维数组全排列并且不会重复排列相同元素。注意如果用递归排列模板将不会排除值相同位置不同的排列,所以不可用,除非在每次有疑似新排列出现之前check其与之前出现的组合是否内容相同。将数组转化为二维数组后,用常用的dfs深搜(从一个分红处开始,一次搜索一个连通区,每搜索一个点将其值赋为0。如果一次深搜结束之后图中还有元素为1,则不是连通图。完整代码如下)判断是否连通,如果连通,ans++。最后输出ans个数即可。完整代码如下:
#include <stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[]={0,0,0,0,0,0,0,1,1,1,1,1};
int ans;
void dfs(int g[3][4],int i,int j){
g[i][j]=0;
if(i+1<=2&&g[i+1][j]==1)dfs(g,i+1,j);
if(j+1<=3&&g[i][j+1]==1)dfs(g,i,j+1);
if(i-1>=0&&g[i-1][j]==1)dfs(g,i-1,j);
if(j-1>=0&&g[i][j-1]==1)dfs(g,i,j-1);
}
bool check(){
int m=0;
int g[3][4];
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
g[i][j]=a[m++];//一维数组转二维数组
}
}
//dfs连通性检测
int cnt=0;
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
if(g[i][j]==1){
dfs(g,i,j);//深搜,标零。如果是全联通,一次深搜后就全为0了,cnt为1;如果不是全联通,cnt大于一
cnt++;
}
}
}
if(cnt==1)return true;
else return false;
}
/*
void f(int k){//全排列
if(k==12){
if(check())
ans++;
}
for(int i=k;i<12;i++){
{int m=a[i];a[i]=a[k];a[k]=m;}
f(k+1);
{int m=a[i];a[i]=a[k];a[k]=m;}
}
}
*/
int main()
{
do{
if(check())ans++;
}while(next_permutation(a,a+12));
cout<<ans;
}
运行结果: