DFS+BFS(广度优先搜索弥补深度优先搜索遍历漏洞求合格条件总数)--09--DFS+BFS--蓝桥杯剪邮票

题目描述

如下图, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连) 
 
比如,下面两张图中,粉红色所示部分就是合格的剪取。 
 
请你计算,一共有多少种不同的剪取方法。 

输出

请填写表示方案数目的整数。 
 
分析1
          使用开锁解锁机制、通过DFS一边搜索一边计数,每积累5个方格就停止进一步搜索,同时将结果存储起来。
   但是3、5、6、7、10(如图)此种情况是DFS做不到的,以下代码只用了DFS,只能得到82种结果。
 1 #include <iostream>
 2 #include <vector>
 3 #include <stdio.h>
 4 #include <queue>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 const int ROW = 3;
 9 const int COL = 4;
10 int sum = 0;
11 int num = 0;
12 int dd[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
13 vector<vector<int> >a(ROW,vector<int>(COL,-1));
14 vector<int>sig[10000];
15 vector<int>zz;
16 vector<int>temp;
17 void rightload(){
18     sig[sum] = temp;
19 }
20 bool checkrightload(){
21     temp = zz;
22     sort(temp.begin(),temp.end());
23     for(int i = 0;i < sum;i++){
24         if(sig[i] == temp)
25             return false;
26     }
27     return true;
28 }
29 void lock(int i,int j){
30     num++;
31     a[i][j] = i*COL+j;
32     zz.push_back(a[i][j]);
33 }
34 void unlock(int i,int j){
35     num--;
36     a[i][j] = -1;
37     zz.pop_back();
38 }
39 void dfs(int i,int j){
40     for(int zz = 0;zz < 4;zz++){
41         int ii = i + dd[zz][0];
42         int jj = j + dd[zz][1];
43         if(ii < 0||jj < 0||ii >= ROW||jj >= COL)
44             continue;
45         if(a[ii][jj] == -1){
46             lock(ii,jj);
47             if(num == 5){
48                 if(checkrightload()){
49                     rightload();
50                     sum++;
51                 }
52             }
53             else
54                 dfs(ii,jj);
55             unlock(ii,jj);
56         }
57     }
58 }
59 int main(){
60     for(int i = 0;i < ROW;i++){
61         for(int j = 0;j < COL;j++){
62             lock(i,j);
63             dfs(i,j);
64             unlock(i,j);
65         }
66     }
67     for(int i = 0;i < sum;i++){
68         for(int j = 0 ;j < 5;j++){
69             cout <<sig[i][j] <<" ";
70         }
71         cout <<endl;
72     }
73     cout << sum <<endl;
74     return 0;
75 }

 分析2

    为了弥补分析1所提出的漏洞,需要用BFS与DFS相结合,才能得到所有情况,以下是BFS与DFS结合解题的代码。

  1 #include <iostream>
  2 #include <vector>
  3 #include <stdio.h>
  4 #include <queue>
  5 #include <cmath>
  6 #include <algorithm>
  7 using namespace std;
  8 const int ROW = 3;
  9 const int COL = 4;
 10 int sum = 0;
 11 int num = 0;
 12 int dd[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
 13 vector<vector<int> >a(ROW,vector<int>(COL,-1));
 14 vector<int>sig[10000];
 15 vector<int>zz;
 16 vector<int>temp;
 17 queue<pair<int,int> >myque;
 18 void rightload(){
 19     sig[sum] = temp;
 20 }
 21 bool checkrightload(){
 22     temp = zz;
 23     sort(temp.begin(),temp.end());
 24     for(int i = 0;i < sum;i++){
 25         if(sig[i] == temp)
 26             return false;
 27     }
 28     return true;
 29 }
 30 void lock(int i,int j){
 31     num++;
 32     a[i][j] = i*COL+j;
 33     zz.push_back(a[i][j]);
 34 }
 35 void unlock(int i,int j){
 36     num--;
 37     a[i][j] = -1;
 38     zz.pop_back();
 39 }
 40 void bfs(int i,int j){
 41     for(int zz = 4;zz >= 0;zz--){
 42         int ii = i + dd[zz][0];
 43         int jj = j + dd[zz][1];
 44         if(ii < 0||jj < 0||ii >= ROW||jj >= COL)
 45             continue;
 46         if(a[ii][jj] == -1){
 47             myque.push({ii,jj});
 48         }
 49     }
 50     while(!myque.empty()){
 51         int ii = myque.front().first;
 52         int jj = myque.front().second;
 53         myque.pop();
 54         lock(ii,jj);
 55         if(num == 5){
 56             if(checkrightload()){
 57                 rightload();
 58                 sum++;
 59             }
 60         }
 61         else{
 62             bfs(ii,jj);
 63         }
 64         unlock(ii,jj);
 65     }
 66 }
 67 void dfs(int i,int j){
 68     for(int zz = 0;zz < 4;zz++){
 69         int ii = i + dd[zz][0];
 70         int jj = j + dd[zz][1];
 71         if(ii < 0||jj < 0||ii >= ROW||jj >= COL)
 72             continue;
 73         if(a[ii][jj] == -1){
 74             lock(ii,jj);
 75             if(num == 5){
 76                 if(checkrightload()){
 77                     rightload();
 78                     sum++;
 79                 }
 80             }
 81             else{
 82                 dfs(ii,jj);
 83             }
 84             bfs(i,j);
 85             unlock(ii,jj);
 86         }
 87     }
 88 }
 89 int main(){
 90     for(int i = 0;i < ROW;i++){
 91         for(int j = 0;j < COL;j++){
 92             lock(i,j);
 93             dfs(i,j);
 94             unlock(i,j);
 95         }
 96     }
 97     for(int i = 0;i < sum;i++){
 98         for(int j = 0 ;j < 5;j++){
 99             cout <<sig[i][j] <<" ";
100         }
101         cout <<endl;
102     }
103     cout << sum <<endl;
104     return 0;
105 }

 

posted @ 2020-02-04 23:11  我只是一个码农  阅读(297)  评论(0编辑  收藏  举报