剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:第一遍dfs取12选5的组合数,将组合数转换为用0和1表示的图(如01234表示如下)
第二遍dfs2测试图的连通性,将相连邮票1置0
最后若有1 则不连通,若全为0,则连通
答案:116代码:
public class CutStamps {
static int[] num = new int[5];//5个组合数
static int[][] map = new int[3][4];// 0 1 图
static boolean[] flag = new boolean[12];//
static int total =0;
public static void main(String[] args) {
dfs(0,0);
System.out.println(total);
}
private static void dfs(int n,int k) {
if(n==5){
for(int j=0;j<5;j++){
//组合数转为0 1 图
map[(num[j])/4][num[j]%4]=1;
}
dfs2((num[0])/4,num[0]%4);
int t =0;
for(int i=0;i<3;i++)
for(int j=0;j<4;j++)
if(map[i][j]==1){
//核查是否连通 顺便将图全部清0
t=1;
map[i][j]=0;
}
if(t==0) {
//此处可打印校验
total++;
}
return;
}
for(int i=k;i<12;i++){
if(flag[i]==false){
flag[i]=true;
num[n]=i;
dfs(n+1,i+1);
flag[i]=false;
}
}
}
//测试五张邮票是否连通
private static void dfs2(int i, int j) {
map[i][j]=0;
if(i>0 && map[i-1][j]==1) dfs2(i-1,j);
if(i<2 && map[i+1][j]==1) dfs2(i+1,j);
if(j>0 && map[i][j-1]==1) dfs2(i,j-1);
if(j<3 && map[i][j+1]==1) dfs2(i,j+1);
}
}