Question:
Result: 116
Solve:
这个题意还是比较好懂的,就是12个数里找出5个数,然后看这5个数在方格中的位置是否相连,
代码也是这个思路,但确实不太好写,我换了好几种方案,最后写成了类似DFS里又套一个DFS的代码。
首先通过深搜去搞出12选5的全部组合,然后通过再一个DFS去判断选出的5个数在方格中是不是连通块
我写的判断连通块的方法是一个最暴力的方法,模拟出方格,然后从选出的第一个数(同时计数为1)开始,判断其四周有没有选出的数,如果有,计数加一,并去dfs那个数,在不断搜索的过程中如果计数到了5,就说明5个数是连在一起的,结果数加一。
上代码吧,注释写的也比较多。
Code:
#include <bits/stdc++.h>
using namespace std;
int cnt, res = 0; //res记录结果
bool vis[4][5]; //标记选出的5个数的坐标
bool vis2[4][5]; //标记5个坐标在dfs过程中是否经过
int dir[4][2] = {1,0,-1,0,0,1,0,-1}; //四个方向
//判断是不是连通块
void dfs(int x, int y)
{
//是连通块,结果加一
if(cnt == 5) res++;
for(int i = 0; i < 4; i++){
int dx = x + dir[i][0];
int dy = y + dir[i][1];
//边界检测,是否已经走过检测
if(vis2[dx][dy] || dx < 1 || dy < 1 || dx > 3 || dy > 4) continue;
//是否为选中数判断
if(!vis[dx][dy]) continue;
cnt++; vis2[dx][dy] = true;
dfs(dx,dy);
}
}
//12选5的全排列
void que(int deep, int num)
{
if(deep > 5){
cnt = 1;
memset(vis2,false,sizeof(vis2));
//找出第一个选出的数字进入连通块判断
for(int i = 1; i <= 3; i++){
for(int j = 1; j <= 4; j++){
if(vis[i][j]){
vis2[i][j] = true;
dfs(i,j);
//判断结束后直接返回
return;
}
}
}
}
//进行全排列,并且将选出的数以坐标的形式标记下来
for(int i = num+1; i <= 12; i++){
if(i%4==0){
vis[i/4][4] = true;
que(deep+1,i);
vis[i/4][4] = false;
}
else{
vis[i/4+1][i%4] = true;
que(deep+1,i);
vis[i/4+1][i%4] = false;
}
}
}
int main(void)
{
memset(vis,false,sizeof(vis));
que(1,0);
cout <<res;
return 0;
}
最后附上蓝桥杯汇总链接:蓝桥杯C/C++A组省赛历年真题题解
声明:图片均来源于蓝桥杯官网,以个人刷题整理为目的,如若侵权,请联系删除~