剪邮票 --全排列和DFS

剪邮票

有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)一维数组转换成二维数组。

  

 

posted @ 2021-03-22 10:22  荣荣荣荣荣荣  阅读(51)  评论(0)    收藏  举报