第四章 搜索(深度、广度搜索、全排列、走迷宫、再解炸弹人、宝岛探险、水管工游戏)

一、深度优先搜索DFS

  深度优先搜索DFS的关键思想是:当下应该怎么做(每个方法都试一遍),这一步解决后,进入下一步,下一步的解决方法和这一步的解决方法是一样的

  DFS的基本模型

  void dfs(int step)

  {

    判断边界

    尝试每一种可能  for(i=1;i<=n;i++)

    {

      继续下一步 dfs(step+1)

    }

    返回

  }

  1.1全排列

 1 //输入一个数n
 2 //输出1-n的全排列
 3 #include <stdio.h>
 4 int n, book[10], a[10];
 5 void dfs(int step)
 6 {
 7     int i;
 8     if (step > n)
 9     {
10         for (i = 1;i <= n;i++)
11         {
12             printf("%d ",a[i]);
13         }
14         printf("\n");
15         return;
16     }
17     for (i = 1;i <= n;i++)
18     {
19         if (book[i] == 0)
20         {
21             a[step] = i;
22             book[i] = 1;
23             dfs(step+1);
24             book[i] = 0;
25         }
26     }
27     return;
28 }
29 int main()
30 {
31     scanf("%d",&n);
32     dfs(1);
33     return 0;
34 }
View Code

  1.2两个三位数相加的结果是三位数,这9个数字各不相同,_ _ _ + _ _ _ = _ _ _

 1 #include <stdio.h>
 2 int total = 0;
 3 int book[10], a[10];
 4 void dfs(int step)
 5 {
 6     int i;
 7     if (step == 10)
 8     {
 9         if (100 * (a[1] + a[4]) + 10 * (a[2] + a[5]) + a[3] + a[6] == 100 * a[7] + 10 * a[8] + a[9])
10         {
11             total++;
12             printf("%d%d%d + %d%d%d = %d%d%d\n",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
13         }
14         return;
15     }
16     for (i = 1;i < 10;i++)
17     {
18         if (book[i] == 0)
19         {
20             book[i] = 1;
21             a[step] = i;
22             dfs(step+1);
23             book[i] = 0;
24         }
25     }
26     return;
27 }
28 int main()
29 {
30     dfs(1);
31     printf("%d\n",total/2);
32     return 0;
33 }
View Code

  1.3走迷宫,解救小哈

 1 #include <stdio.h>
 2 int n, m, map[10][10], book[10][10],endx, endy,minstep=978978;
 3 void dfs(int x, int y, int step)
 4 {
 5     int i,tx,ty;
 6     int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
 7     if (x == endx&&y == endy)
 8     {
 9         if (minstep > step)
10             minstep = step;
11         return;
12     }
13     for (i = 0;i < 4;i++)
14     {
15         tx = x + next[i][0];
16         ty = y + next[i][1];
17         if (tx<1 || ty<1 || tx>n || ty>m)
18             continue;
19         if (map[tx][ty] == 0 && book[tx][ty] == 0)
20         {
21             book[tx][ty] = 1;
22             dfs(tx,ty,step+1);
23             book[tx][ty] = 0;
24         }
25     }
26     return;
27 }
28 int main()
29 {
30     int i, j, startx, starty;
31     scanf("%d%d",&n,&m);
32     for (i = 1;i <= n;i++)
33     {
34         for (j = 1;j <= m;j++)
35         {
36             scanf("%d",&map[i][j]);
37         }
38     }
39     scanf("%d%d%d%d",&startx,&starty,&endx,&endy);
40 
41     dfs(startx,starty,0);
42     
43     printf("%d\n",minstep);
44     return 0;
45 }
View Code

 二、广度优先搜索BFS

  深度优先搜索DFS——递归

  广度优先搜索BFS——队列 

  继续走迷宫 

 1 #include <stdio.h>
 2 int n, m, endx, endy;
 3 int map[10][10], book[10][10];
 4 struct node
 5 {
 6     int x;
 7     int y;
 8     int step;
 9 };
10 void bfs(int startx,int starty)
11 {
12     struct node queue[100];
13     int head, tail;
14     int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
15     int i, tx, ty, flag = 0;
16     head = 1;tail = 1;
17     queue[tail].x = startx;
18     queue[tail].y = starty;
19     queue[tail].step = 0;
20     tail++;
21     book[startx][starty] = 1;
22     while (head<tail)
23     {
24         for (i = 0;i < 4;i++)
25         {
26             tx = queue[head].x + next[i][0];
27             ty = queue[head].y + next[i][1];
28             if (tx<1 || ty<1 || tx>n || ty>m)
29             {
30                 continue;
31             }
32             if (map[tx][ty] == 0 && book[tx][ty] == 0)
33             {
34                 book[tx][ty] = 1;
35                 queue[tail].x = tx;
36                 queue[tail].y = ty;
37                 queue[tail].step = queue[head].step + 1;
38                 tail++;
39             }
40             if (tx == endx&&ty == endy)
41             {
42                 flag = 1;
43                 break;
44             }
45         }
46         if (flag == 1)
47             break;
48         head++;
49     }
50     printf("%d\n",queue[tail-1].step);
51 
52 }
53 int main()
54 {
55     int i, j,startx,starty;
56     scanf("%d%d",&n,&m);
57     for (i = 1;i <= n;i++)
58     {
59         for (j = 1;j <= m;j++)
60         {
61             scanf("%d",&map[i][j]);
62         }
63     }
64     scanf("%d%d%d%d",&startx,&starty,&endx,&endy);
65     bfs(startx,starty);
66     return 0;
67 }
View Code

三、再解炸弹人

  现在炸弹不是想放在那里就能放在那里的了,必须由小人能够走到的地方才能放置炸弹。比如下面这个例子小人默认站在(3,3)这个位置。请问放在何处最多可以消灭多个敌人。

   

输入

13 13 3 3
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G...G.....#
#G#.#G###.#G#
#...G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############
输出
将炸弹放置在(7,11)处,最多可以消灭10个敌人。
  1 #include <stdio.h>
  2 char map[20][20];
  3 int n, m, book[20][20];
  4 int max=0, maxx, maxy;
  5 struct node
  6 {
  7     int x;
  8     int y;
  9 };
 10 int fun(int x,int y)
 11 {
 12     int sum = 0, k;
 13     k = x;
 14     while (map[k][y] != '#'&&k >= 0)
 15     {
 16         if (map[k][y] == 'G')
 17             sum++;
 18         k--;
 19     }
 20     k = x;
 21     while (map[k][y] != '#'&&k < n)
 22     {
 23         if (map[k][y] == 'G')
 24             sum++;
 25         k++;
 26     }
 27     k = y;
 28     while (map[x][k] != '#'&&k >= 0)
 29     {
 30         if (map[x][k] == 'G')
 31             sum++;
 32         k--;
 33     }
 34     k = y;
 35     while (map[x][k] != '#'&&k <m)
 36     {
 37         if (map[x][k] == 'G')
 38             sum++;
 39         k++;
 40     }
 41     return sum;
 42 }
 43 void dfs(int x,int y)
 44 {
 45     int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
 46     int i,tx,ty;
 47     int sum = fun(x, y);
 48     if (max < sum)
 49     {
 50         max = sum;
 51         maxx = x;
 52         maxy = y;
 53     }
 54     for (i = 0;i < 4;i++)
 55     {
 56         tx = x + next[i][0];
 57         ty = y + next[i][1];
 58         if (tx < 0 || tx >= n || ty < 0 || ty >= m)
 59             continue;
 60         if (map[tx][ty] == '.'&&book[tx][ty] == 0)
 61         {
 62             book[tx][ty] = 1;
 63             dfs(tx,ty);
 64         }
 65     }
 66     return;
 67 }
 68 void bfs(int x,int y)
 69 {
 70     struct node queue[200];
 71     int head, tail,i,tx,ty,sum;
 72     int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
 73     head = 0;
 74     tail = 0;
 75     queue[tail].x = x;
 76     queue[tail].y = y;
 77     tail++;
 78     while (head < tail)
 79     {
 80         for (i = 0;i < 4;i++)
 81         {
 82             tx = queue[head].x + next[i][0];
 83             ty = queue[head].y + next[i][1];
 84             if (tx < 0 || tx >= n || ty < 0 || ty >= m)
 85                 continue;
 86             if (map[tx][ty] == '.'&&book[tx][ty] == 0)
 87             {
 88                 queue[tail].x = tx;
 89                 queue[tail].y = ty;
 90                 tail++;
 91                 sum = fun(tx, ty);
 92                 book[tx][ty] = 1;
 93                 if (sum > max)
 94                 {
 95                     max = sum;
 96                     maxx = tx;
 97                     maxy = ty;
 98                 }
 99             }
100         }
101         head++;
102     }
103 }
104 int main()
105 {
106     int i,startx,starty;
107     scanf("%d%d%d%d",&n,&m,&startx,&starty);
108     getchar();
109     for (i = 0;i < n;i++)
110         gets(map[i]);
111     max = fun(startx,starty);
112     maxx = startx;
113     maxy = starty;
114     book[startx][starty] = 1;
115     //dfs(startx,starty);
116     bfs(startx,starty);
117     printf("max=%d,x=%d,y=%d\n",max,maxx,maxy);
118     return 0;
119 }
View Code

四、宝岛探险

 

问题一
小哼降落后,所在岛屿的面积大小
输入地图和降落位置(从序号1开始)
输出降落所在位置的岛屿面积
例子
输入:
10 10 6 8
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0
输出:
38
 
 1 //问题一,计算面积,分别使用广度、深度搜索,进行面积计算
 2 #include <stdio.h>
 3 int n, m, map[50][50], book[50][50],sum;
 4 int next[4][2] = { {-1,0},{1,0},{0,1},{0,-1} };
 5 
 6 struct node
 7 {
 8     int x;
 9     int y;
10 };
11 void bfs(int x,int y)
12 {
13     struct node queue[1000];
14     int head=1, tail=1,pcur=1;
15     int i,tx,ty;
16     queue[tail].x = x;
17     queue[tail].y = y;
18     tail++;
19     book[x][y] = 1;
20     while (pcur < tail)
21     {
22         for (i = 0;i < 4;i++)
23         {
24             tx = queue[pcur].x + next[i][0];
25             ty = queue[pcur].y + next[i][1];
26             if (tx<1 || tx>n || ty<1 || ty>m)
27                 continue;
28             if (book[tx][ty] == 0 && map[tx][ty] > 0)
29             {
30                 queue[tail].x = tx;
31                 queue[tail].y = ty;
32                 book[tx][ty] = 1;
33                 tail++;
34             }
35         }
36         pcur++;
37     }
38     printf("%d\n",tail-1);
39 }
40 
41 void dfs(int x,int y)
42 {
43     int tx, ty, i, j;
44     sum++;
45     for (i = 0;i < 4;i++)
46     {
47         tx = x + next[i][0];
48         ty = y + next[i][1];
49         if (tx<1 || tx>n || ty<1 || ty>m)
50             continue;
51         if (book[tx][ty] == 0 && map[tx][ty] > 0)
52         {
53             book[tx][ty] = 1;
54             dfs(tx,ty);
55         }
56     }
57     return;
58 }
59 
60 int main()
61 {
62     int startx, starty, i, j;
63     scanf("%d%d%d%d",&n,&m,&startx,&starty);
64     for (i = 1;i <= n;i++)
65     {
66         for (j = 1;j <= m;j++)
67         {
68             scanf("%d", &map[i][j]);
69         }
70     }
71     //bfs(startx,starty);
72     book[startx][starty] = 1;
73     dfs(startx,starty);
74     printf("%d\n",sum);
75     return 0;
76 }
View Code
 
问题二
小哼降落后,所在岛屿的面积大小
输入地图和降落位置(从序号1开始)
输出降落所在位置的岛屿
例子
输入:
10 10 6 8
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0
输出:
   1   2   1   0   0   0   0   0   2   3
   3   0   2   0  -1  -1  -1   0   1   2
   4   0   1   0  -1  -1  -1  -1   0   1
   3   2   0   0   0  -1  -1  -1   0   0
   0   0   0   0   0   0  -1  -1  -1   0
   0  -1  -1  -1   0  -1  -1  -1  -1   0
   0  -1  -1  -1  -1  -1  -1  -1  -1   0
   0   0  -1  -1  -1  -1  -1  -1   0   0
   0   0   0  -1  -1  -1  -1   0   1   2
   0   0   0   0   0   0   0   0   1   0
 1 //问题二,面积标记,分别使用广度、深度搜索,进行面积标记
 2 #include <stdio.h>
 3 int n, m, map[50][50], book[50][50],sum;
 4 int next[4][2] = { {-1,0},{1,0},{0,1},{0,-1} };
 5 
 6 struct node
 7 {
 8     int x;
 9     int y;
10 };
11 void bfs(int x,int y)
12 {
13     struct node queue[1000];
14     int head=1, tail=1,pcur=1;
15     int i,tx,ty;
16     queue[tail].x = x;
17     queue[tail].y = y;
18     tail++;
19     book[x][y] = 1;
20     while (pcur < tail)
21     {
22         for (i = 0;i < 4;i++)
23         {
24             tx = queue[pcur].x + next[i][0];
25             ty = queue[pcur].y + next[i][1];
26             if (tx<1 || tx>n || ty<1 || ty>m)
27                 continue;
28             if (book[tx][ty] == 0 && map[tx][ty] > 0)
29             {
30                 queue[tail].x = tx;
31                 queue[tail].y = ty;
32                 book[tx][ty] = 1;
33                 tail++;
34             }
35         }
36         pcur++;
37     }
38     //printf("%d\n",tail-1);
39 }
40 
41 void dfs(int x,int y)
42 {
43     int tx, ty, i, j;
44     sum++;
45     for (i = 0;i < 4;i++)
46     {
47         tx = x + next[i][0];
48         ty = y + next[i][1];
49         if (tx<1 || tx>n || ty<1 || ty>m)
50             continue;
51         if (book[tx][ty] == 0 && map[tx][ty] > 0)
52         {
53             book[tx][ty] = 1;
54             dfs(tx,ty);
55         }
56     }
57     return;
58 }
59 void print_map()
60 {
61     int i, j;
62     for (i = 1;i <= n;i++)
63     {
64         for (j = 1;j <= m;j++)
65         {
66             if (book[i][j])
67             {
68                 map[i][j] = -1;
69             }
70             printf("%d ",map[i][j]);
71         }
72         printf("\n");
73     }
74 }
75 int main()
76 {
77     int startx, starty, i, j;
78     scanf("%d%d%d%d",&n,&m,&startx,&starty);
79     for (i = 1;i <= n;i++)
80     {
81         for (j = 1;j <= m;j++)
82         {
83             scanf("%d", &map[i][j]);
84         }
85     }
86     //bfs(startx,starty);
87     book[startx][starty] = 1;
88     dfs(startx,starty);
89     //printf("%d\n",sum);
90     print_map();
91     return 0;
92 }
View Code
 1 //问题二,面积标记,分别使用广度、深度搜索,进行面积标记
 2 //dfs、着色法
 3 #include <stdio.h>
 4 int n, m, map[50][50], book[50][50],sum;
 5 int next[4][2] = { {-1,0},{1,0},{0,1},{0,-1} };
 6 
 7 void dfs(int x,int y,int color)
 8 {
 9     int tx, ty, i, j;
10     sum++;
11     map[x][y] = color;
12     for (i = 0;i < 4;i++)
13     {
14         tx = x + next[i][0];
15         ty = y + next[i][1];
16         if (tx<1 || tx>n || ty<1 || ty>m)
17             continue;
18         if (book[tx][ty] == 0 && map[tx][ty] > 0)
19         {
20             book[tx][ty] = 1;
21             dfs(tx,ty,color);
22         }
23     }
24     return;
25 }
26 void print_map()
27 {
28     int i, j;
29     for (i = 1;i <= n;i++)
30     {
31         for (j = 1;j <= m;j++)
32         {
33             printf("%d ",map[i][j]);
34         }
35         printf("\n");
36     }
37 }
38 int main()
39 {
40     int startx, starty, i, j;
41     scanf("%d%d%d%d",&n,&m,&startx,&starty);
42     for (i = 1;i <= n;i++)
43     {
44         for (j = 1;j <= m;j++)
45         {
46             scanf("%d", &map[i][j]);
47         }
48     }
49     //bfs(startx,starty);
50     book[startx][starty] = 1;
51     dfs(startx,starty,-1);
52      
53     print_map();
54     return 0;
55 }
View Code
问题三
求出地图中小岛个数
例子
输入:
10 10
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0
输出:
  -1  -1  -1   0   0   0   0   0  -2  -2
  -1   0  -1   0  -3  -3  -3   0  -2  -2
  -1   0  -1   0  -3  -3  -3  -3   0  -2
  -1  -1   0   0   0  -3  -3  -3   0   0
   0   0   0   0   0   0  -3  -3  -3   0
   0  -3  -3  -3   0  -3  -3  -3  -3   0
   0  -3  -3  -3  -3  -3  -3  -3  -3   0
   0   0  -3  -3  -3  -3  -3  -3   0   0
   0   0   0  -3  -3  -3  -3   0  -4  -4
   0   0   0   0   0   0   0   0  -4   0
 
View Code

五、水管工游戏

 

题目输入:5行4列的图,0表示树木
5 4
5 3 5 3
1 5 3 0
2 3 5 1
6 1 1 5
1 5 5 4
输出:
(1,1) (1,2) (2,2) (3,2) (3,3) (3,4) (4,4) (5,4)
不可能时输出impossible
 
使用深度搜索,在每个方格内dfs需要的参数为,方格坐标x,y,水管的进口(如下图数字表示),以及改方格的水管类型,改方格是否使用过

问题一:找到通道

 1 //水管工,深度搜索
 2 #include <stdio.h>
 3 int map[50][50], book[50][50];
 4 int n, m,flag;
 5 void dfs(int x,int y,int open)
 6 {
 7     if (x == n&&y == m+1)
 8     {
 9         flag = 1;
10         return;
11     }
12     if (x<1 || x>n || y<1 || y>m)
13         return;
14     if (book[x][y])
15         return;
16     book[x][y] = 1;
17     if (map[x][y] > 0 && map[x][y] <= 4)
18     {
19         if (open == 1)
20         {
21             dfs(x-1,y,4);
22             dfs(x+1,y,2);
23         }
24         if (open == 2)
25         {
26             dfs(x,y+1,1);
27             dfs(x,y-1,3);
28         }
29         if (open == 3)
30         {
31             dfs(x-1,y,4);
32             dfs(x+1,y,2);
33         }
34         if (open == 4)
35         {
36             dfs(x, y - 1, 3);
37             dfs(x, y + 1, 1);
38         }
39     }
40     if (map[x][y] == 5 || map[x][y] == 6)
41     {
42         if (open == 1)
43             dfs(x,y+1,1);
44         if (open == 2)
45             dfs(x+1,y,2);
46         if (open == 3)
47             dfs(x,y-1,3);
48         if (open == 4)
49             dfs(x-1,y,4);
50     }
51     book[x][y] = 0;
52     return;
53 }
54 int main()
55 {
56     int i, j;
57     scanf("%d%d",&n,&m);
58     for (i = 1;i <= n;i++)
59     {
60         for (j = 1;j <= m;j++)
61             scanf("%d",&map[i][j]);
62     }
63     dfs(1,1,1);
64     if (flag)
65         printf("路径存在\n");
66     else
67         printf("路径不存在\n");
68     return 0;
69 }
View Code

问题二:输出路径

 

 1 //水管工,深度搜索
 2 #include <stdio.h>
 3 int map[50][50], book[50][50];
 4 int n, m,flag;
 5 struct node
 6 {
 7     int x;
 8     int y;
 9 }s[100];
10 int top = 0;
11 void dfs(int x,int y,int open)
12 {
13     int i;
14     if (x == n&&y == m+1&&open==1)
15     {
16         flag = 1;
17         for (i = 0;i < top;i++)
18         {
19             printf("(%d,%d) ", s[i].x, s[i].y);
20         }
21         printf("\n");
22         return;
23     }
24     if (x<1 || x>n || y<1 || y>m)
25         return;
26     if (book[x][y])
27         return;
28     book[x][y] = 1;
29     s[top].x = x;
30     s[top].y = y;
31     top++;
32     if (map[x][y] > 0 && map[x][y] <= 4)
33     {
34         if (open == 1)
35         {
36             dfs(x-1,y,4);
37             dfs(x+1,y,2);
38         }
39         if (open == 2)
40         {
41             dfs(x,y+1,1);
42             dfs(x,y-1,3);
43         }
44         if (open == 3)
45         {
46             dfs(x-1,y,4);
47             dfs(x+1,y,2);
48         }
49         if (open == 4)
50         {
51             dfs(x, y - 1, 3);
52             dfs(x, y + 1, 1);
53         }
54     }
55     if (map[x][y] == 5 || map[x][y] == 6)
56     {
57         if (open == 1)
58             dfs(x,y+1,1);
59         if (open == 2)
60             dfs(x+1,y,2);
61         if (open == 3)
62             dfs(x,y-1,3);
63         if (open == 4)
64             dfs(x-1,y,4);
65     }
66     book[x][y] = 0;
67     top--;
68     return;
69 }
70 int main()
71 {
72     int i, j;
73     scanf("%d%d",&n,&m);
74     for (i = 1;i <= n;i++)
75     {
76         for (j = 1;j <= m;j++)
77             scanf("%d",&map[i][j]);
78     }
79     dfs(1,1,1);
80     if (flag)
81     {
82         printf("路径存在\n");
83         //加在这里是错误的,原因是,递归函数变化过程中,会把结果的s重新改变
84         //应在递归函数结束时,直接打印出来
85         /*for (i = 0;i < top;i++)
86         {
87             printf("(%d,%d) ", s[i].x, s[i].y);
88         }
89         printf("\n");*/
90     }
91     else
92         printf("路径不存在\n");
93     return 0;
94 }
View Code

 

posted @ 2017-06-06 20:54  daisy_ding  阅读(294)  评论(0)    收藏  举报