蓝桥杯第七届省赛第七题-剪邮票

蓝桥杯第七届省赛第七题-剪邮票

如图在这里插入图片描述
, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,
在这里插入图片描述
在这里插入图片描述

中,粉红色所示部分就是合格的剪取。

在看到这个题目时我首先想到的是用DFS来解决,但是在看到图三的时候我发现,DFS取不出来这种剪发,因为题目强调的是所有邮票是连通的但不是只能“一条路走到底”,我们会发现在图三中不管从哪个方向走到6号格子,都会同时面临两个选择,而这两个选择确是这种剪发的组成部分,但是DFS只能选择一个方向一直走下去,不能同时走这两个方向!!在发现了这个bug后我又发现了DFS解决这个题的不足之处,那就是以为图一例,这种剪发在DFS里是两种剪发,分别以2和12为起点,但是还有一些取法,只有一种可能,这就造成了去重的困难,使得单纯的DFS解法失去了用武之地。那怎么解决喃?我想的是可以先将从12个里面选取5个的组合先找出来,然后一个一个的测试其连通性,但是这又遇到了一个问题,那就是如果以一个二维数组来模拟这个方格,那么找出这样的组合又太过于复杂了,因为要两个数字来表示一个格子,要找出5个数字,就需要10个数字来表示,太过于复杂了,于是我在网上发现了一种神奇的操作,自认为远远想不到,于是使用了这种思想将这个题目做出来了,但是还是觉得记录一下较好。

代码:

//这个题用纯粹的DFS会存在一些遍历不到的情况,例如图三,不论从哪个方向走到6,都会面临同时走两个方向的困境,而DFS同时只能选一个方向走到底。
//此题只能先找出5个的组合形式,然后对每个形式用DFS测试其是否联通!!!
//这里使用一种方法用一维数组模拟二维数组及其移动情况!! 
#include<iostream> 
using namespace std;
int Map[12]={
    
    1,2,3,4,6,7,8,9,11,12,13,14};//注意这里二维数组的特殊取数,只有这样的取数才能用一定的规律去模拟其移动情况!! 
int vis[5],Conp[5];
int dir[4]={
    
    -5,+5,-1,+1};
int res=0;
void Dfs(int n){
    
    
	for(int i=0;i<4;i++){
    
    
		int temp = Conp[n]+dir[i];
		if(temp<1 || temp>14 || temp==10 || temp==5)
			continue;
		for(int j=0;j<5;j++){
    
    		
			if(vis[j]==0 && Conp[j]==temp){
    
    //这是一种DFS的变形的想法,用来判断多点是否连通!! 
				vis[j]=1;
				Dfs(j);				
			}
		}
	}	
}
int main(){
    
    	
	for(int a=0;a<12;a++)
		for(int b=a+1;b<12;b++)
			for(int c=b+1;c<12;c++)
				for(int d=c+1;d<12;d++)
					for(int e=d+1;e<12;e++){
    
    
						Conp[0]=Map[a];
						Conp[1]=Map[b];
						Conp[2]=Map[c];
						Conp[3]=Map[d];
						Conp[4]=Map[e];
						for(int i=0;i<5;i++)
							vis[i]=0;
						vis[0]=1;
						Dfs(0);
						int flag=1;
						for(int i=0;i<5;i++)
							flag*=vis[i];
						if(flag==1)
							res++;						
					}
		cout<<res<<endl;
		return 0;
}

答案:116

猜你喜欢

转载自blog.csdn.net/weixin_46610759/article/details/108229004