剪邮票
有12张连在一起的的12生肖邮票,现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)请你计算,一共有多少种不同的剪去方法。


看到这个题一开始我直接认为DFS搜索12次就行了。
肯定没那么简单。因为有几种情况是搜索不到的,比如:

可以转换成一个思路,就是随机找个5张邮票,看它们能不能凑成一张大邮票;
#include <stdio.h>
int cnt = 0, ans = 0;
int a[5];//用来存放,组合数列
int next[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
int book[50][50];
int g[50][50];
void dfs(int x, int y){
int i;
cnt++;
book[x][y] = 1;
for(i = 0; i < 4; i++){
int tx = x + next[i][0];
int ty = y + next[i][1];
if(tx >= 0 && tx < 3 && ty >= 0 && ty < 4 && book[tx][ty] == 0 && g[tx][ty] == 1){
dfs(tx, ty);
}
}
}
void solve(int step, int k){
int i;
if(step == 5){
int x, y;
for(i = 0; i < 5; i++){
x = (a[i] - 1) / 4;
y = (a[i] - 1) % 4;
g[x][y] = 1;
}
dfs((a[0] - 1) / 4, (a[0] - 1) % 4);
if(cnt == 5){
ans++;
}
cnt = 0;
memset(g,0,sizeof(g));
memset(book,0,sizeof(book));
}
for(i = k + 1; i <= 12; i++){
a[step] = i;
solve(step + 1, i);
}
}
int main() {
int i, j;
solve(0, 0);
printf("%d\n",ans);
return 0;
}
注意问题:
以后在搜索地图的时候一定要把book[x][y]写在刚进函数时,而不是写在进函数前,否则初始点可能会被忘记记录,一定要养成习惯,在for循环里不多BB!
题目知识点:
(1)数的全排列,是每次的排列组合里面的数都是不完全一样的,例如 有 1 2 3 4 5 就不会再出现 1 2 3 5 4.
(2)一维数组转换成二维数组。