具体问题描述如下:
剪邮票
如下图, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,下面两个图中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:
这道题可以分成两个部分,一部分是从12张邮票选5张邮票,另一部分是检验这5张邮票是否满足条件。
12选5显然是一个组合问题,可以利用深度优先搜索实现12选5。检验5张邮票是否满足条件可以利用广度优先搜索遍历,如果从某个邮票可以遍历到其他所有选择的4个邮票则证明这5张邮票是连续的。
12选5的具体代码如下:
public class Compose {
static boolean[] result = new boolean[13];
public static void f(int step, int count) {
if (count >= 5) {
int tempcount=0;
//输出选好的5张邮票
for(int i=1;tempcount<5;i++)
if(result[i])
System.out.print(i+" ");
} else {
if (step > 12)
return;
//选编号为step的邮票
result[step] = true;
f(step + 1, count + 1);
//不选编号为step的邮票
result[step] = false;
f(step + 1, count);
}
}
public static void main(String[] args) {
int step = 1;
f(step, 0);
System.out.println(tcount);
}
}
最终代码如下:
import java.awt.Point;
import java.util.LinkedList;
import java.util.Queue;
public class Compose {
static boolean[] result = new boolean[13];
public static int tcount = 0;
public static int[][] position = { { 0, -1 }, { 0, 1 }, { -1, 0 }, { 1, 0 } };
public static void f(int step, int count) {
if (count >= 5) {
boolean[][] matrix = new boolean[5][6];
int tempcount = 0;
Point min = new Point();
//将线性表转成邮票矩阵
for (int i = 1; tempcount < 5; i++) {
if (result[i]) {
int x = 1 + (i - 1) / 4;
int y = 1 + (i - 1) % 4;
if (min.x == 0)
min = new Point(x, y);
matrix[x][y] = true;
tempcount++;
}
}
//下面是从min节点开始深度优先搜索遍历
tempcount = 0;
Queue<Point> queue = new LinkedList<Point>();
queue.offer(min);
boolean[][] select = new boolean[5][5];
select[min.x][min.y] = true;
while (!queue.isEmpty()) {
min = queue.poll();
for (int[] c : position)
if (matrix[min.x + c[0]][min.y + c[1]]
&& !select[min.x + c[0]][min.y + c[1]]) {
queue.offer(new Point(min.x + c[0], min.y + c[1]));
select[min.x + c[0]][min.y + c[1]] = true;
}
tempcount++;
}
if (tempcount == 5)
tcount++;
} else {
if (step > 12)
return;
result[step] = true;
f(step + 1, count + 1);
result[step] = false;
f(step + 1, count);
}
}
public static void main(String[] args) {
int step = 1;
f(step, 0);
System.out.println(tcount);
}
}