蓝桥杯 剪邮票
剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:深搜找到 12 个数中 5个数的组合,然后使用广度优先搜索判断选出的5个是否联通。
错误思路 1:使用直接使用深度搜索,由于深度搜索过程中不会转弯以下的情况搜索不到

图片来自 :https://blog.csdn.net/eventqueue/article/details/50954641
2:不使用bfs判断联通,而是直接判断 上下左右是否有联通的点,以下情况错误
1 1 1 0
0 0 0 0
0 1 1 0
代码:
public class Stamp {
public static int num = 0;
public static int[] vis = new int[5];
public static int[][] next = {{0,1},{1,0},{0,-1},{-1,0}};
public static int[][] stamp = new int[3][4];
public static int[] visit = new int[12];
public static int[] have = new int[5];
///
public static void main(String[] args) {
dfs(0,0);
System.out.println(num);
}
///select five visiable number
public static void dfs(int step,int i){
if(step >= 5){
if(bfs()){
num++;
}
return;
}
for(;i<12;i++){
if(visit[i] == 0){
visit[i] = 1;
have[step] = i;
stamp[i/4][i%4] = 1;
dfs(step+1,i+1);
stamp[i/4][i%4] = 0;
visit[i] = 0;
}
}
}
///justify if accessable
public static boolean bfs(){
Queue<Integer> q = new LinkedList<Integer>();
q.offer(have[0]);
stamp[have[0]/4][have[0]%4] = -1;
int step = 1;
while(q.peek()!=null){
int e = q.poll();
for(int j=0;j<4;j++){
int ni = e/4+next[j][0];
int nj = e%4+next[j][1];
if(ni<3 && ni>-1 && nj<4 && nj>-1 && stamp[ni][nj] == 1){
stamp[ni][nj] = -1;
step++;
q.offer(ni*4+nj);
}
}
}
/// offset
for(int i=0;i<5;i++){
int h = have[i];
stamp[h/4][h%4] = 1;
}
return step == 5;
}
///exit
/*
1 1 1 0 0
0 0 0 0 0
0 1 1 0 0
*/
///don't work
public static boolean justify(){
//search first node
boolean flag = false;
for(int i=0;i<5;i++){
// up down left right
for(int j=0;j<4;j++){
int ni = have[i]/4+next[j][0];
int nj = have[i]%4+next[j][1];
if(ni<3 && ni>-1 && nj<4 && nj>-1 && stamp[ni][nj] == 1){
flag = true;
break;
}
}
if(!flag){
return false;
}
else{
flag = false;
}
}
return true;
}
}

浙公网安备 33010602011771号