蓝桥杯第七届G题:剪邮票+bfs

题目描述

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

这个题我先是用的dfs来做,但是写到后面发现剪枝太麻烦了,考虑的因素太多,然后参考了一些大佬的思路写了两种方法。

方法一(bfs):

先绘制地图1~12,然后枚举5个不同数字,这五个不同数字都对应一个坐标,把这5个坐标进行标记,在进行dfs。最后判断这五个位置是否有没走过的即可。
答案:116

代码:

#include<stdio.h>
#include<queue>
using namespace std;
int mp[3][4],arr[5];//mp地图数组;arr升序数组,选取5个数 
bool vis[3][4];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 
struct Node{
	int x,y;
}n;
bool bfs()
{
	int num=0,x,y;
	for(int i=0;i<3;i++)
		for(int j=0;j<4;j++)
			if(arr[num]==mp[i][j])	vis[i][j]=true,num++,x=i,y=j;//arr数组里面存的是升序数字 ,所以可以顺序遍历。 
			else	vis[i][j]=false;
	n.x=x;//从最后一个数字开始遍历 
	n.y=y;
	queue<Node>q;
	q.push(n);
	vis[x][y]=false;
	while(!q.empty())
	{
		Node res=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			int dx=res.x+dir[i][0];
			int dy=res.y+dir[i][1];
			if(!vis[dx][dy]||dx<0||dy<0||dx>=3||dy>=4)	continue;
			vis[dx][dy]=false;
			n.x=dx;
			n.y=dy;
			q.push(n);
		}		
	}
	for(int i=0;i<3;i++)
		for(int j=0;j<4;j++)//如果是dfs没走到的数字,则不满足条件 
			if(vis[i][j])	return false;
	return true;
}
int main()
{
	for(int i=0;i<3;i++)
		for(int j=0;j<4;j++)
			mp[i][j]=i*4+j+1;
	int cnt=0;
	for(arr[0]=1;arr[0]<13;arr[0]++)
		for(arr[1]=arr[0]+1;arr[1]<13;arr[1]++)
			for(arr[2]=arr[1]+1;arr[2]<13;arr[2]++)
				for(arr[3]=arr[2]+1;arr[3]<13;arr[3]++)
					for(arr[4]=arr[3]+1;arr[4]<13;arr[4]++)
							if(bfs())	cnt++;
	printf("%d",cnt);
	return 0;
}

方法二(堆栈):

从12个数字中选取5个升序数字,将第一个数放进栈,然后将栈顶元素出栈,跟他满足相连条件的其他数一并入栈。依次进行上次操作。最后判断这五个数字有没有没进入栈的情况即可。

代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stack>
using namespace std;
int arr[5];
bool vis[5];
bool cheak(int i,int j)//判断是否满足条件 
{
	if((i==4&&j==5) || (i==5&&j==4))	return false;
	if((i==8&&j==9) || (i==9&&j==8))	return false;
	if(abs(i-j)==1 || abs(i-j)==4)	return true;
	return false;	
}
bool slove()
{
	memset(vis,false,sizeof(vis));
	stack<int>s;
	s.push(arr[0]);
	vis[0]=true;
	while(!s.empty())
	{
		int res=s.top();
		s.pop();
		for(int i=0;i<5;i++)
		{
			if(vis[i]||!cheak(res,arr[i]))	continue;
			vis[i]=true;
			s.push(arr[i]);
		}
	}
	for(int i=0;i<5;i++)//是否有没入栈的条件 
		if(!vis[i])	return false;
	return true;
}
int main()
{
	int cnt=0;
	for(arr[0]=1;arr[0]<13;arr[0]++)
		for(arr[1]=arr[0]+1;arr[1]<13;arr[1]++)
			for(arr[2]=arr[1]+1;arr[2]<13;arr[2]++)
				for(arr[3]=arr[2]+1;arr[3]<13;arr[3]++)
					for(arr[4]=arr[3]+1;arr[4]<13;arr[4]++)
						if(slove())	cnt++;
	printf("%d",cnt);
	return 0;	
}
发布了67 篇原创文章 · 获赞 1 · 访问量 1306

猜你喜欢

转载自blog.csdn.net/qq_45249273/article/details/104863768