剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
参考链接:https://blog.csdn.net/u014552756/article/details/50946197
先从12个数中选取5个数,根据组合公式可以算出一种有792种情况。
接下来判断每一种情况是否符合相邻要求,由图可得,方格的上下左右分别为-4,+4,-1,+1;如果以此来判断是否相邻会出现BUG,比如:3,4,5,7,8这种情况是不符合要求的,但是5在4+1后被错误判定为符合情况,如果要解决这种BUG,要附加上更多的判断条件,所以可以将原图改为:
这样在4,9,14增加1后,都不会达到左边边缘,解决了这种BUG。
在得到了一种组合后,如何判断是否满足相邻要求,是难点,可以利用DFS判断是否满足从一个点出发是否可以搜索到全部的点。
public class Main{ static long res=0; static int book[]=new int[5]; static int arr[]=new int[5]; static int dir[]={-5,+5,-1,+1}; //上下左右 static void judge(int n){ for(int i=0;i<4;i++){ int dx=arr[n]+dir[i]; if(dx<1 || dx>14 || dx==5 || dx==10){ continue; } for(int j=0;j<5;j++){ if(book[j]==0 && dx==arr[j]){ book[j]=1; judge(j); //进入此点 } } } } public static void main(String[] args){ int mp[]={0,1,2,3,4,6,7,8,9,11,12,13,14}; for(int a=1;a<=8;a++){ for(int b=a+1;b<=9;b++){ for(int c=b+1;c<=10;c++){ for(int d=c+1;d<=11;d++){ for(int e=d+1;e<=12;e++){ arr[0]=mp[a]; arr[1]=mp[b]; arr[2]=mp[c]; arr[3]=mp[d]; arr[4]=mp[e]; //产生一种全排列 book[0]=1; judge(0); int flag=0; for(int i=0;i<5;i++){ if(book[i]==0){ flag=1; } book[i]=0; } if(flag==0){ res++; } } } } } } System.out.println(res); } }