蓝桥杯.剪邮票(DFS)

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组省赛历年真题题解 

声明:图片均来源于蓝桥杯官网,以个人刷题整理为目的,如若侵权,请联系删除~

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UmVfX1BvaW50

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值