蓝桥杯-剪邮票(连通块问题)
题在这里
http://oj.ecustacm.cn/problem.php?id=1286
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int N=6;
int a[N][N];
int b[N][N];
int sum;
int ss[10000];
void dfs(int x,int y,int s)
{
if(x<1||x>3||y<1||y>4) return ;
if(a[x][y]!=1||b[x][y]!=0) return;
if(a[x+1][y]==1||a[x-1][y]==1||a[x][y+1]==1||a[x][y-1]==1) ss[s]++;
else return;
b[x][y]=1;
dfs(x+1,y,s);
dfs(x-1,y,s);
dfs(x,y+1,s);
dfs(x,y-1,s);
}
int main()
{
int idx;
int m;
for(int i=0;i<pow(2,12);i++)
{
idx=0;
m=0;
int tmp=i;
for(int j=1;j<=3;j++)
for(int k=1;k<=4;k++)
{
a[j][k]=tmp%2;
tmp/=2;
idx+=a[j][k];
}
//上面这一块是将所有的情况都列出来
//详情见 https://blog.csdn.net/m0_52169223/article/details/115041748
if(idx==5)//只选择五个数字的情况
{
int ww=1;
memset(b,0,sizeof(b));
for(int j=1;j<=3;j++)
for(int k=1;k<=4;k++)
{
ss[m+1]=0;
if(a[j][k]==1) dfs(j,k,++m);
if(ss[m]==5&&ww==1)//单个连通块有五个格子
{
ww=0;//一次就够了,否则会造成重复
sum++;
}
}
}
}
cout<<sum;
return 0;
}
蓝桥杯-方格分割
题在这里
http://oj.ecustacm.cn/problem.php?id=1320
//这一题和剪邮票差不多
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int N=10;
int a[N][N];
int b[N][N];
int sum;
int ss[100000];
//这里的ss[]并不需要多大
void dfs(int x,int y,int s)
{
if(x<1||x>6||y<1||y>6) return ;
if(a[x][y]!=1||b[x][y]!=0) return;
if(a[x+1][y]==1||a[x-1][y]==1||a[x][y+1]==1||a[x][y-1]==1) ss[s]++;
else return;
b[x][y]=1;
dfs(x+1,y,s);
dfs(x-1,y,s);
dfs(x,y+1,s);
dfs(x,y-1,s);
}
int main()
{
int m;
int ww;
for(int i=0;i<pow(2,18);i++)
{
int tmp=i;
for(int j=1;j<=3;j++)
for(int k=1;k<=6;k++)
{
a[j][k]=tmp%2;
a[7-j][7-k]=1-tmp%2;
//确保对称
tmp/=2;
}
ww=1;
m=0;
memset(b,0,sizeof(b));
//初始化b[][],b[][]表示此处是否拜访过
for(int j=1;j<=6;j++)
for(int k=1;k<=6;k++)
{
//以防不是从第一个开始的,当我们对这个正确情况深搜后,令ww==0,就让我们结束
if(ww==0) break;
//这一步相当于剪枝
ss[m+1]=0;
if(a[j][k]==1) dfs(j,k,++m);
//dfs中找到只有18个格子,并且连通
if(ss[m]==18&&ww==1)
{
ww=0;
sum++;
}
}
}
cout<<sum/4;
//旋转对称,镜面对称都属于同一种分割法。
return 0;
}