剪邮票
如【图1.jpg】, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
图1.jpg
图2.jpg
图3.jpg
思路:从12张邮票中随机选5个,判断所选的5个是否连在一起。时间复杂度为O(2^12*5)。
import java.util.Arrays;
public class Main {
final int MAXN = 15;
int res;
int a[][] = { { 1, 2, 3, 4, }, { 5, 6, 7, 8, }, { 9, 10, 11, 12 } };
int dy[] = { 0, 1, 0, -1 };
int dx[] = { 1, 0, -1, 0 };
boolean vis[] = new boolean[MAXN];
boolean include(int b[], int e) {
for (int i = 0; i < 5; ++i) {
if (b[i] == e) {
return true;
}
}
return false;
}
int connected(int y, int x, int b[]) {
int num = 0;
vis[y * 4 + x + 1] = true;
for (int i = 0; i < 4; ++i) {
int ny = y + dy[i];
int nx = x + dx[i];
int e = ny * 4 + nx + 1;
if (0 <= ny && ny < 3 && 0 <= nx && nx < 4 && !vis[e] && include(b, e)) {
num += connected(ny, nx, b);
}
}
return num + 1;
}
void dfs(int dep, int k, int b[]) {
if (dep == 12) {
if (k == 5) {
Arrays.fill(vis, false);
if (connected((b[0] - 1) / 4, (b[0] - 1) % 4, b) == 5) {
res++;
}
}
return;
}
b[k] = a[dep / 4][dep % 4];
dfs(dep + 1, k + 1, b);
dfs(dep + 1, k, b);
}
Main() {
res = 0;
int[] b = new int[MAXN];
dfs(0, 0, b);
System.out.println(res);
}
public static void main(String[] args) {
new Main();
}
}