剪邮票

剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:先找到5个数的组合,然后从第一个数字开始遍历,经过上下左右操作检测5个数是否都被访问一遍,如果5个数都可以遍历到则种类+1。

坑点分析:

在原图中向上为-4,向下为+4,向左为-1,向右为+1,但是遇到3 4 5 7 8这种4+1=5但是这种情况不符合,所以重构一下原图:

这样,向上为-5,向下为+5,向左为-1,向右为+1,避免了每行最后一个+1后等于下一行第一个的情况。


思路参考:https://blog.csdn.net/u014552756/article/details/50946197 
 

package 二月十四号真题训练;
/*
剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
 * */
public class No_7 {
    static int arr[]=new int[5];
    static int map[]={1,2,3,4,6,7,8,9,11,12,13,14}; //1.坑点:见上面分析
    static int vis[]=new int[5];
    static int dis[]= {-5,5,-1,1};
    static int a,b,c,d,e,count=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
          for(a=0;a<12;a++)            //a,b,c,d,e分别是五张邮票每一张的下标,相当于从12中随机挑选出5个数来,而且为了保证没有重复,遵循a<b<c<d<e原则进行选取,这样不会出现选取重复现象
        	  for(b=0;b<12;b++)
        		  if(b>a)
        		  for(c=0;c<12;c++)
        			  if(c>b)
        			  for(d=0;d<12;d++)
        				  if(d>c)
        				  for(e=0;e<12;e++)
        					  if(e>d)
        				  {
        						 arr[0]=map[a];
        						 arr[1]=map[b];
        						 arr[2]=map[c];
        						 arr[3]=map[d];
        						 arr[4]=map[e];
        						 for(int i=0;i<5;i++)//因为此题的特殊性,vis不用回溯,所以每次都要把vis数组置0
        							 vis[i]=0;
        						 vis[0]=1;  //vis[i]数组记录此点有没有邻居,vis[0]=1,默认是有邻居的
        					     dfs(0);
        				  }
          System.out.println(count);
	}
	private static void dfs(int num) {
		// TODO Auto-generated method stub
		if(vis[0]==1&&vis[1]==1&&vis[2]==1&&vis[3]==1&&vis[4]==1)
		{
			count++;return;            //当五个点都有邻居,则符合题目要求,count++
		}
		for(int i=0;i<4;i++)
		{   
			for(int k=0;k<5;k++)
		   {
			 if(arr[k]==arr[num]+dis[i]&&vis[k]!=1) //对于每个下标是num的邮票,寻找是否有没被访问过的邻居节点(vis[k]!=1)与其相邻,若找到则标记邻居节点vis[k]=1;并对其进行dfs
			 {
				 vis[k]=1;
				 dfs(k);   //注意不要回溯,因为能走到这一步则说明下标为k的邮票肯定有邻居,如果加一条回溯,则这个点便无效作废,但是这个点是有意义的
			 }
		   }
		}}}


 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值