蓝桥杯:剪邮票->用最简单的递归实现

        这个是老生常谈的经典图遍历题目了。但是网上大神的代码答案,多多少少都运用了比较复杂的递归实现。这样对于刚入门的小白来说,首先是要花较长时间理解,其次就是好像只会用这个方法做了,很难有普遍性,学到套路。委屈 别问我为什么知道。 大笑
          所以我一直想找个最简单最基本的BFS递归方法,就能做出来,结果还行。 大笑废话不多说,先贴题......(运用c/c++实现)

第一步:如图先稍微改一下题目


第二步:先不管相不相连,先从12筛选出5个彼此不同的数,排除重复数字的可能(如 2 2 6 7 9 13)

        在12个数的所有5个数组合中, 筛选出随机抽取5个不同数的组合(即12个糖拿5个的所有拿法),则还剩120种可能,存起来。


第三步:每找到一个符合第二步的可能(5个数一组),就利用第一步图中的改进版的上下左右中的关系,筛选出满足 5个数每个              数都至少与一个同组数字相邻的的可能。排除那些在本组中有独立数字的可能(即1+4的可能)
例:


        排除   5=4+1的可能

- >在排除 4+1 可能后,还剩下 5=2+3 和 5=0+5 两种可能了 大笑

   
  5=2+3    
 
       5 = 0+5 这正是我们要找的可能
 


第四步:创建一个 map[15][15] 的图的邻接表,由于第三步筛选时肯定会遍历相邻两个数字的连线两次的,所以正好符合邻接表的条件,这样每种可能在第三步筛选结束后,都建立了一个邻接表(即一个图)。
第五步:调用最基础的DFS算法对第四步生成的邻接表进行遍历,如果这个可能是可以访问5个数的,就是符合题意的,我们的最终结果就加一。
        最基本的DFS算法,天然无添加剂 大笑
     void DFS(int V1) // 最基础的深度优先遍历:递归实现         V1是访问结点
    {
         int i;
         map[V1][V1] = 1;
         nod_num++;
         for(i=0;i<15;i++) // 节点数
              if(map[V1][i]!=0 && i!=V1) // 查找相邻结点
                   if(!map[i][i])  // 如果没有访问
         DFS(i);
    }

完成了!就是那么简单就可以!就是用最简单的递归就实现了哦! 偷笑      下面贴出完整代码.......

#include<iostream>
#include<string.h>
using namespace std; // 答案:116

int map[15][15],nod_num;
void DFS(int V1) // 最基础的深度优先遍历:递归实现
{
	int i;
	map[V1][V1] = 1;
	nod_num++;
	for(i=0;i<15;i++) // 节点数
		if(map[V1][i]!=0 && i!=V1) // 查找相邻结点
		 if(!map[i][i])  // 如果没有访问
			DFS(i);
}

int fine(int a[])
{
	nod_num=0;
	memset(map,0,sizeof(map));
	for(int b(0);b<5;b++)
		for(int c(0);c<5;c++)
			if((a[b] == a[c]+1) || (a[b] == a[c]-5) || (a[b] == a[c]+5) || (a[b] == a[c]-1)) // 第三步:每组的每个元素至少与另一个元素相邻
			{
				int v1(a[b]),v2(a[c]); // 第四步:	若数字v1与数字v2 相邻,则有两条连线。
										//  		则经过上个if后 v1-v2 将被遍历为所有相邻的连线
				map[v1][v2]=1; // 建立邻接表
				map[v2][v1]=1;
			}
	DFS(a[0]);  // 第五步:对第四步生成的邻接表进行遍历,如果这个可能是可以访问5个数的,就是符合题意的
	if(nod_num==5) return 1;
	return 0;
}

int main() // 外部调用
{
	int z[12] = {1,2,3,4,6,7,8,9,11,12,13,14}; // 第一步:图数组
	int a[5];
	int num(0),num1(0);
	for(int i(0);i<12;i++)
		for(int j(i+1);j<12;j++)
			for(int k(j+1);k<12;k++)
	  			for(int l(k+1);l<12;l++)
					for(int m(l+1);m<12;m++) // 第二步:筛选出12个数中随机抽取5个不同数的组合。(用最简单的暴力for就可以解决)
						{
							a[0]=z[i];
							a[1]=z[j];
							a[2]=z[k];
							a[3]=z[l];
							a[4]=z[m];
							num1++;
							if(fine(a)) num++;
						}
	cout<<"12个剪切连续5个方法数:  "<<num<<endl<<"12个选5个的可能数:   "<<num1<<endl;
	return 0;
}
          如需转载请注明出处!谢谢!



猜你喜欢

转载自blog.csdn.net/weixin_41094315/article/details/80100045
今日推荐