剪邮票
有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:组合+连通图
import java.util.LinkedList;
import java.util.Queue;
public class Text1 {
static int[] a={1,2,3,4,5,6,7,8,9,10,11,12};
static int[] num=new int[5];
static int[] arr=new int[5];
static int N=a.length;
static int M=num.length;
static int sum=0;
public static void main(String[] args) {
f(N,M);
System.out.println(sum);
}
//组合
private static void f(int n, int m) {
int i,j;
for(i=m;i<=n;i++) {
num[m-1] = i-1;
if(m>1)
f(i-1,m-1);
else{
for ( j = 0; j <=M-1; j++) {
arr[j]=a[num[j]];
}
if(bfs(arr))
sum++;
}
}
}
//相当于连通图解法
private static boolean bfs(int[] arr2) {
Queue<Integer> queue=new LinkedList<>();
int[] dx={0,1,0,-1},dy={1,0,-1,0};
int s=0,x,y;
int[][] bfs=new int[4][5];
for (int i = 0; i < 5; ++i) {
x=(arr2[i]-1)/4;
y=(arr2[i]-1)%4;
bfs[x][y]=1;
}
queue.add(arr2[0]-1);
while(!queue.isEmpty()){
int q=queue.poll();
for (int i = 0; i <4; ++i) {
x=q/4+dx[i];
y=q%4+dy[i];
if(x<3 && y<4 && x>=0 && y>=0 && bfs[x][y]==1){
queue.add(x*4+y);
bfs[x][y]=0;
s++;
}
}
}
if(s==5) return true;
return false;
}
}