剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路
用五个for循环嵌套找到五个数的组合,从第一个数开始遍历,经过上下左右操作检测5个数是否满足相邻条件,如果5个数都可以遍历到则种类+1。
但是有个问题,在图中,向上为-4,向下为+4,向左为-1,向右为+1,如果遇到3,4,5,7,8这种情况,4+1=5,但4和5不相邻,我参考了另一篇博
客,按照这位博主的思路,将原图重构了下,真的觉得很妙哇,这样,向上为-5,向下为+5,向左为-1,向右为+1,避免了每行最后一个+1后
等于下一行第一个的情况。
原博主链接 https://blog.csdn.net/u014552756/article/details/50946197
博主写的c++,我按照他的思路写了一份Java版本的
public class Main{
static int stamp[] = {1,2,3,4,6,7,8,9,11,12,13,14};
static int[] aa = new int[5];
static boolean[] vis =new boolean[5];
static int sum=0;
static int conn[] = {-1,1,-5,5}; //用来进行上下左右操作
private static void dfs(int n) {
for (int i = 0; i < 4; i++) {
int t = aa[n] + conn[i];
if ( t < 1 || t > 14 || t == 5 || t == 10 ) continue;
for (int j = 0; j < 5; j++) {
if (!vis[j]&&aa[j]==t) { //不为vis不为true且进行的上下左右操作后可以到达某个相邻的数
vis[j] = true;
dfs(j);
}
}
}
}
public static void main(String[] args) {
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++) {
aa[0] = stamp[a];
aa[1] = stamp[b];
aa[2] = stamp[c];
aa[3] = stamp[d];
aa[4] = stamp[e];
for (int i=0; i < 5; i++) {
vis[i] = false; //初始化标记为false,即没被访问过
}
vis[0] = true; //第一个标记为true
dfs(0); //通过递归去遍历
boolean flag = true;
for (int i = 0; i < 5; i++) {
if (!vis[i]) {
flag = false; //五个数之间存在没被连通
break;
}
}
if (!flag) continue; //不连通,直接继续下一个数检验
else sum++; //连通,种类加一
//继续下一个数的循环和遍历访问,如一开始为1,2,3,4,6,则进入循环的下一个自增数对1,2,3,4,7检验
}
System.out.println(sum);
}
}