先附上题目内容
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
这个题目有点像迷宫问题,一开始想的是用dfs算法去遍历出所有的5段长的路径,可是不知道怎么去重。后来还是借助了csdn上的大佬的思路来解题
这个题的规模较小,所以我们可以对1到12暴力枚举出含有5个数的所有组合,然后对每一个组合进行连通性检测,如果是连通的则进行累加。
明白了解题思路之后,来看一下代码实现:
首先需要暴力枚举出所有组合:
public static void main(String[] args) {
int count=0;
for(a[0] = 0;a[0]<12;a[0]++)
for(a[1] = a[0]+1;a[1]<12;a[1]++)
for(a[2] = a[1]+1;a[2]<12;a[2]++)
for(a[3] = a[2]+1;a[3]<12;a[3]++)
for(a[4] = a[3]+1;a[4]<12;a[4]++)
{
if(judge()) 这个是后面判断连通性的函数
count++;
}
System.out.println(count);
}
判断连通性需要先建立一个布尔类型的visit[5]的数组,用dfs去找所有的点,找到的话就把对应的visit置true,遍历完之后,如果是连通的则visit数组全部为true。
private static boolean judge() {
boolean visit[] = new boolean [5];
dfs(visit,0);
return visit[0]&&visit[1]&&visit[2]&&visit[3]&&visit[4];
}
找点是有规律的,同一行的两个点连接的话,它们的数值是相差1的。同一列的两个点连接的话,它们的数值是相差4的。
private static void dfs(boolean[] visit, int i) {
visit[i] = true; 每次进入一个新的点就把visit置为true
for(int j=0;j<visit.length;j++) {
if(!visit[j]&&(a[i]/4==a[j]/4)&&(a[i]-1==a[j] || a[i]+1==a[j])) 判断同一行的且相差1的
dfs(visit,j);
if(!visit[j]&&(a[i]%4==a[j]%4)&&(a[i]-4==a[j] || a[i]+4==a[j])) 判断同一列的且相差4的
dfs(visit,j);
}
}