剪邮票
题目描述:
如【图1.jpg】, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解题思路:
1.将12个序号存在数组numb中;
2.利用二维矩阵存放块与块之间的关系(0为不相邻,1位相邻)因为是对称的(1和2相邻等价于2和1相邻)所以存一半即可;
1 2 3 4 5 6 7 8 9 10 11 12
1 0 1 0 0 1 0 0 0 0 0 0 0
2 0 0 1 0 0 1 0 0 0 0 0 0
3 0 0 0 1 0 0 1 0 0 0 0 0
4 0 0 0 0 0 0 0 1 0 0 0 0
5 0 0 0 0 0 1 0 0 1 0 0 0
6 0 0 0 0 0 0 1 0 0 1 0 0
7 0 0 0 0 0 0 0 1 0 0 1 0
8 0 0 0 0 0 0 0 0 0 0 0 1
9 0 0 0 0 0 0 0 0 0 1 0 0
10 0 0 0 0 0 0 0 0 0 0 1 0
11 0 0 0 0 0 0 0 0 0 0 0 1
12 0 0 0 0 0 0 0 0 0 0 0 0
3.递归求其子序列返回长度为5的子序列;
4.对子序列进行判断,如果5个相连,则count++;
5.输出count即为题解
代码实现:
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
String []numb ={"1 ","2 ","3 ","4 ","5 ","6 ","7 ","8 ","9 ","10 ","11 ","12 "};
Integer [][]flog = new Integer[13][13]; //二维矩阵用来存块与块之间的连接关系
for(int i=0;i<flog.length;i++) { //将矩阵全部赋初值为0
for(int j=0;j<flog[i].length;j++) {
flog[i][j]=0;
}
}
flog[1][2]=1;flog[1][5]=1;flog[2][6]=1;flog[2][3]=1; //赋值相连的边为1
flog[3][7]=1;flog[3][4]=1;flog[4][8]=1;
flog[5][6]=1;flog[5][9]=1;flog[6][7]=1;flog[6][10]=1;
flog[7][8]=1;flog[7][11]=1;flog[8][12]=1;
flog[9][10]=1;flog[10][11]=1;
flog[11][12]=1;
List<String> list = new LinkedList<>();
String s = "";
subsequence(numb,list,0,s,0);
int count =0;
for(String i : list) {
String []str = i.split(" ");
Set<String> p = new HashSet<>(); // 集合用来判断是否连接,若链接加入set集合
for(int m=0;m<str.length;m++) {
for(int n=m;n<str.length;n++) {
if(flog[Integer.parseInt(str[m])][Integer.parseInt(str[n])]==1) {
p.add(str[m]);p.add(str[n]);
}
}
}
if(p.size()==5) {
count++;
}
}
System.out.println(count);
}
//求子序列函数返回长度为5的子序列
public static void subsequence(String []numb,List<String> ans,int index,String s,int count) {
if(index == numb.length) {
if(count==5) {
ans.add(s);
}
return;
}
String no = s;
subsequence(numb,ans,index+1,no,count);
String yes = s + String.valueOf(numb[index]);
if(count<5) {
subsequence(numb,ans,index+1,yes,count+1);
}
}
}
复杂度分析:
若是n张邮票,剪k张相连的。
其时间复杂度为:O(N*K^2),空间复杂度为:O(N)。