首页 > 代码库 > 第四章、万能的搜索

第四章、万能的搜索


第一节、深度优先搜索
p78 输出全排列的 dfs 方法

#include <stdio.h>int a[10],book[10],n;void dfs(int step){  int i;  if(step==n+1)  {    for(i=1;i<=n;i++)      printf("%d",a[i]);    printf("\n");    return;  }  for(i=1;i<=n;i++)  {    if(book[i]==0)    {      a[step]=i;      book[i]=1;      dfs(step+1);      book[i]=0;    }  }  return;}int main(){  scanf("%d",&n);  dfs(1);  getchar();  return 0;}
View Code


为了深入了解深搜,用两个方法改变程序:
1、

#include <stdio.h>int a[10],book[10],n;void dfs(int step){  int i;  if(step==n+1)  {    for(i=1;i<=n;i++)      printf("%d",a[i]);    printf("\n");    return;  }  for(i=1;i<=n;i++)  {    if(book[i]==0)    {      a[step]=i;      book[i]=1;      dfs(step+1);      printf("i is %d\n",i); // 加这句,观察回溯过程      book[i]=0;    }  }  return;}int main(){  //scanf("%d",&n);  n=3;  dfs(1);  getchar();  return 0;}
View Code


2、

#include <stdio.h>int a[10],n;void dfs(int step){  int i;  if(step==n+1)  {    for(i=1;i<=n;i++)      printf("%d",a[i]);    printf("\n");    return;  }  for(i=1;i<=n;i++)  {    //把标志与回溯都去掉了。这样没有了剪枝,就可以走遍全部节点    a[step]=i;    dfs(step+1);  }  return;}int main(){  scanf("%d",&n);  dfs(1);  getchar();  return 0;}
View Code

 


p80 1~9九个数填空的DFS方法
( 9!=362880 )

#include <stdio.h>int a[10],book[10],total=0;void dfs(int step){  int i;  if(step==10)  {    if(a[1]*100+a[2]*10+a[3] + a[4]*100+a[5]*10+a[6] ==       a[7]*100+a[8]*10+a[9])    {      total++;      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]);    }    return;  }  for(i=1;i<=9;i++)  {    if(book[i]==0)    {      a[step]=i;      book[i]=1;      dfs(step+1);      book[i]=0;    }  }  return;}int main(){  dfs(1);  printf("total=%d",total/2);  getchar();  return 0;}
View Code
#include <stdio.h>int a[10],book[10],total=0,sum=0;void dfs(int step){  int i;  if(step==10)  {    sum++;    if(a[1]*100+a[2]*10+a[3] + a[4]*100+a[5]*10+a[6] ==       a[7]*100+a[8]*10+a[9])    {      total++;      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]);    }    return;  }  for(i=1;i<=9;i++)  {    if(book[i]==0)    {      a[step]=i;      book[i]=1;      dfs(step+1);      book[i]=0;    }  }  return;}int main(){  dfs(1);  printf("total=%d,sum=%d",total/2,sum);  getchar();  return 0;}
View Code


第二节、解救小哈
p85 用DFS来寻找解救小哈的最短路径数

#include <stdio.h>int n,m,p,q,min=99999999;int a[51][51],book[51][51];void dfs(int x,int y,int step){  int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} };  int tx,ty,k;  if(x==p && y==q)  {    if(step<min) min=step;    return;  }    for(k=0;k<=3;k++)  {    tx=x+next[k][0]; //next第一列    ty=y+next[k][1]; //第二列    if(tx<1 || tx>n || ty<1 || ty>m) //新坐标越界      continue;    if(a[tx][ty]==0 && book[tx][ty]==0) //新坐标未走过,且无路障    {      book[tx][ty]=1;      dfs(tx,ty,step+1);      book[tx][ty]=0;    }  }  return;}int main(){  int i,j,startx,starty;  scanf("%d %d",&n,&m); //行、列  for(i=1;i<=n;i++)    for(j=1;j<=m;j++)      scanf("%d", &a[i][j]);  scanf("%d %d %d %d",&startx,&starty,&p,&q); //起点与终点坐标  book[startx][starty]=1;  dfs(startx,starty,0);  printf("%d",min);  getchar();  return 0;}/*5 40 0 1 00 0 0 00 0 1 00 1 0 00 0 0 11 1 4 3*/
View Code

 


第三节、广度优先搜索
p92 BFS解救小哈

#include <stdio.h>struct note{  int x;  int y;  int f;  int s;};int main(){  struct note que[2501];  int a[51][51]={0},book[51][51]={0};  int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} };  int head, tail;  int i, j, k, n, m, startx, starty, p, q, tx, ty, flag;  scanf("%d %d", &n, &m); //行、列  for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);  scanf("%d %d %d %d", &startx, &starty, &p, &q); //起点与终点坐标  head = 1;  tail = 1;  que[tail].x = startx;  que[tail].y = starty;  que[tail].f = 0;  que[tail].s = 0;  tail++;  book[startx][starty] = 1;  flag = 0;  while(head < tail)  {    for(k = 0; k <= 3; k++)    {      tx = que[head].x + next[k][0];      ty = que[head].y + next[k][1];      if(tx < 1 || tx > n || ty < 1 || ty > m) //新坐标越界        continue;      if(a[tx][ty] == 0 && book[tx][ty] == 0)  //新坐标未走过,且无路障      {        book[tx][ty] = 1;        que[tail].x = tx;        que[tail].y = ty;        que[tail].f = head;        que[tail].s = que[head].s + 1;        tail++;      }      if(tx == p && ty == q)      {        flag = 1;        break;      }    }    if(flag == 1)      break;    head++;  }    printf("%d\n", que[tail - 1].s);  getchar(); getchar();  return 0;}/*5 40 0 1 00 0 0 00 0 1 00 1 0 00 0 0 11 1 4 3*/
View Code

 


第四节、再解炸弹人
p98 广搜解炸弹人

#include <stdio.h>struct note{  int x;  int y;};char a[20][21];int getnum(int i, int j){  int sum, x, y;  sum = 0;    //向上统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    x--;  }    //向下统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    x++;  }    //向左统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    y--;  }    //向右统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    y++;  }    return sum;}int main(){  struct note que[401];  int head,tail;  int book[20][20]={0};  int i,k,sum,max=0,mx,my,n,m,startx,starty,tx,ty;    int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} };                       scanf("%d %d %d %d", &n, &m, &startx, &starty); //n行,m列  起始坐标                       for(i = 0; i <= n - 1; i++)    scanf("%s", a[i]);    head=1;  tail=1;  que[tail].x=startx;  que[tail].y=starty;  tail++;  book[startx][starty]=1;  max=getnum(startx,starty);  mx=startx;  my=starty;  while(head<tail)  {    for(k = 0; k <= 3; k++)    {      tx = que[head].x + next[k][0];      ty = que[head].y + next[k][1];            if(tx < 0 || tx > n-1 || ty < 0 || ty > m-1) //新坐标越界        continue;      if(a[tx][ty] == . && book[tx][ty] == 0)  //新坐标未走过,且无路障      {        book[tx][ty] = 1;        que[tail].x = tx;        que[tail].y = ty;        tail++;        sum=getnum(tx,ty);                //printf("haha %d %d %d\n",tx,ty,sum); //可以观察中间输出过程                if(sum>max)        {          max=sum;          mx=tx;          my=ty;        }      }    }    head++;  }    //printf("将炸弹放置在(%d,%d),最多可以消灭%d个敌人\n", mx,my,max);  printf("bomp here:(%d,%d),most is:%d\n",mx,my,max);  getchar();  getchar();  return 0;}/*p66 (6,11)改为平地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##############*/
View Code


p103 深搜解炸弹人

#include <stdio.h>char a[20][21];int book[20][20],max,mx,my,n,m;int getnum(int i, int j){  int sum, x, y;  sum = 0;    //向上统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    x--;  }    //向下统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    x++;  }    //向左统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    y--;  }    //向右统计可以消灭的敌人数  x = i; y = j;  while(a[x][y] != #)  {    if(a[x][y] == G)      sum++;    y++;  }    return sum;}void dfs(int x,int y){  int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} };    int k,sum,tx,ty;  sum=getnum(x,y);    if(sum>max)  {    max=sum;    mx=x;    my=y;  }    for(k = 0; k <= 3; k++)  {    tx = x + next[k][0];    ty = y + next[k][1];        if(tx < 0 || tx > n-1 || ty < 0 || ty > m-1) //新坐标越界      continue;    if(a[tx][ty] == . && book[tx][ty] == 0)  //新坐标未走过,且无路障    {        book[tx][ty] = 1;        dfs(tx,ty);    }  }   return;}  int main(){  int i,startx,starty;  scanf("%d %d %d %d", &n, &m, &startx, &starty); //n行,m列  起始坐标                       for(i = 0; i <= n - 1; i++)    scanf("%s", a[i]);    book[startx][starty]=1;  max=getnum(startx,starty);  mx=startx;  my=starty;  dfs(startx,starty);  //printf("将炸弹放置在(%d,%d),最多可以消灭%d个敌人\n", mx,my,max);  printf("bomp here:(%d,%d),most is:%d\n",mx,my,max);  getchar();  getchar();  return 0;}/*p66 (6,11)改为平地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##############*/
View Code

 


第五节、宝岛探险
p107 广搜计算小岛面积

#include <stdio.h>struct note{  int x;  int y;};int main(){  struct note que[2501];  int head,tail;  int a[51][51];  int book[20][20]={0};  int i,j,k,sum,n,m,startx,starty,tx,ty;    int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} };                       scanf("%d %d %d %d", &n, &m, &startx, &starty); //n行,m列  起始坐标                       for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);   head=1;  tail=1;  que[tail].x=startx;  que[tail].y=starty;  tail++;  book[startx][starty]=1;  sum=1;  while(head<tail)  {    for(k = 0; k <= 3; k++)    {      tx = que[head].x + next[k][0];      ty = que[head].y + next[k][1];            if(tx < 1 || tx > n || ty < 1 || ty > m) //新坐标越界        continue;      if(a[tx][ty] > 0 && book[tx][ty] == 0)  //是陆地,且新坐标未走过      {        sum++;        book[tx][ty] = 1;        que[tail].x = tx;        que[tail].y = ty;        tail++;      }    }    head++;  }  printf("%d\n",sum);  getchar();  getchar();  return 0;}/*10 10 6 81 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 00 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0*/
View Code


p110 深搜计算小岛面积

#include <stdio.h>int a[51][51];int book[51][51],n,m,sum;void dfs(int x,int y){  int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} };    int k,tx,ty;  for(k = 0; k <= 3; k++)  {    tx = x + next[k][0];    ty = y + next[k][1];        if(tx < 1 || tx > n || ty < 1 || ty > m) //新坐标越界        continue;    if(a[tx][ty] > 0 && book[tx][ty] == 0)  //是陆地,且新坐标未走过    {      sum++;      book[tx][ty] = 1;      dfs(tx,ty);    }  }   return;}  int main(){  int i,j,startx,starty;  scanf("%d %d %d %d", &n, &m, &startx, &starty); //n行,m列  起始坐标                       for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);   book[startx][starty]=1;  sum=1;  dfs(startx,starty); //  printf("%d\n",sum);  getchar(); getchar();  return 0;}/*10 10 6 81 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 00 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0*/
View Code


p112 小岛区域成-1

#include <stdio.h>int a[51][51];int book[51][51],n,m,sum;  int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} }; //放在这里可能更清楚void dfs(int x,int y,int color){  int k,tx,ty;  a[x][y]=color; //当前点着色。下面是扩展点。。  for(k = 0; k <= 3; k++)  {    tx = x + next[k][0];    ty = y + next[k][1];        if(tx < 1 || tx > n || ty < 1 || ty > m) //新坐标越界        continue;    if(a[tx][ty] > 0 && book[tx][ty] == 0)  //是陆地,且新坐标未走过    {      sum++;      book[tx][ty] = 1;      dfs(tx,ty,color); //一旦调用dfs,就着色    }  }   return;}  int main(){  int i,j,startx,starty;  scanf("%d %d %d %d", &n, &m, &startx, &starty); //n行,m列  起始坐标                       for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);   book[startx][starty]=1;  sum=1;  dfs(startx,starty,-1); //  for(i = 1; i <= n; i++)  {    for(j = 1; j <= m; j++)      printf("%3d", a[i][j]);     printf("\n");  }  printf("%d\n",sum);  getchar(); getchar();  return 0;}/*10 10 6 81 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 00 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0*/
View Code


p114 计算小岛个数之漫水填充法

#include <stdio.h>int a[51][51];int book[51][51],n,m; //sum用不着了  int next[4][2] = { {0,1},                     {1,0},                     {0,-1},                     {-1,0} }; //放在这里可能更清楚void dfs(int x,int y,int color){  int k,tx,ty;  a[x][y]=color; //当前点着色。下面是扩展点。。  for(k = 0; k <= 3; k++)  {    tx = x + next[k][0];    ty = y + next[k][1];        if(tx < 1 || tx > n || ty < 1 || ty > m) //新坐标越界        continue;    if(a[tx][ty] > 0 && book[tx][ty] == 0)  //是陆地,且新坐标未走过    {      //sum++;      book[tx][ty] = 1;      dfs(tx,ty,color); //一旦调用dfs,就着色    }  }   return;}  int main(){  int i,j,num=0;  scanf("%d %d", &n, &m); //n行,m列  起始坐标不必有了                       for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);   //枚举着色  for(i = 1; i <= n; i++)  {    for(j = 1; j <= m; j++)    {      if(a[i][j]>0)      {        num--;        book[i][j]=1;        dfs(i,j,num); //      }    }  }  for(i = 1; i <= n; i++)  {    for(j = 1; j <= m; j++)      printf("%3d", a[i][j]);     printf("\n");  }  printf("Number is:%d\n",-num); //小岛个数  getchar(); getchar();  return 0;}/*10 101 2 1 0 0 0 0 0 2 33 0 2 0 1 2 1 0 1 24 0 1 0 1 2 3 2 0 13 2 0 0 0 1 2 4 0 00 0 0 0 0 0 1 5 3 00 1 2 1 0 1 5 4 3 00 1 2 3 1 3 6 2 1 00 0 3 4 8 9 7 5 0 00 0 0 3 7 8 6 0 1 20 0 0 0 0 0 0 0 1 0*/
View Code

 


第六节、水管工游戏
p121 DFS解水管工游戏

#include <stdio.h>int a[51][51];int book[51][51],n,m,flag=0;void dfs(int x,int y,int front){  if(x==n && y==m+1) //已经出口  {    flag=1;    return;  }    if(x < 1 || x > n || y < 1 || y > m) //坐标越界    return;  if( book[x][y] == 1)    return;  book[x][y]=1;  if(a[x][y]>=5 && a[x][y]<=6) //直管  {    if(front==1) dfs(x,y+1,1);    if(front==2) dfs(x+1,y,2);          if(front==3) dfs(x,y-1,3);    if(front==4) dfs(x-1,y,4);  }  if(a[x][y]>=1 && a[x][y]<=4) //弯管  {    if(front==1)    {      dfs(x+1,y,2);      dfs(x-1,y,4);    }    if(front==2)    {      dfs(x,y+1,1);      dfs(x,y-1,3);    }        if(front==3)    {      dfs(x-1,y,4);      dfs(x+1,y,2);    }        if(front==4)    {      dfs(x,y+1,1);      dfs(x,y-1,3);    }      }    book[x][y]=0; //取消标记,即回溯  return;}int main(){  int i,j;  scanf("%d %d", &n, &m); //n行,m列                       for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);   dfs(1,1,1);  if(flag==0)    printf("impossible\n");  else    printf("possible\n");  getchar(); getchar();  return 0;}/*5 45 3 5 31 5 3 02 3 5 16 1 1 51 5 5 4*/
View Code


p124 DFS解水管工游戏,输出路径

#include <stdio.h>int a[51][51];int book[51][51],n,m,flag=0;struct note{  int x;  int y;} s[100];int top=0;void dfs(int x,int y,int front){  int i;  if(x==n && y==m+1) //已经出口  {    flag=1;    for(i=1;i<=top;i++)      printf("(%d,%d) ",s[i].x,s[i].y);    return;  }    if(x < 1 || x > n || y < 1 || y > m) //坐标越界    return;  if( book[x][y] == 1)    return;  book[x][y]=1;  //将当前尝试的坐标入栈  top++;  s[top].x=x;  s[top].y=y;  if(a[x][y]>=5 && a[x][y]<=6) //直管  {    if(front==1) dfs(x,y+1,1);    if(front==2) dfs(x+1,y,2);          if(front==3) dfs(x,y-1,3);    if(front==4) dfs(x-1,y,4);  }  if(a[x][y]>=1 && a[x][y]<=4) //弯管  {    if(front==1)    {      dfs(x+1,y,2);      dfs(x-1,y,4);    }    if(front==2)    {      dfs(x,y+1,1);      dfs(x,y-1,3);    }        if(front==3)    {      dfs(x-1,y,4);      dfs(x+1,y,2);    }        if(front==4)    {      dfs(x,y+1,1);      dfs(x,y-1,3);    }      }    book[x][y]=0; //取消标记,即回溯  top--; // 将当前尝试的坐标出栈  return;}int main(){  int i,j;  scanf("%d %d", &n, &m); //n行,m列                       for(i = 1; i <= n; i++)    for(j = 1; j <= m; j++)      scanf("%d", &a[i][j]);   dfs(1,1,1);  if(flag==0)    printf("impossible\n");  getchar(); getchar();  return 0;/*5 45 3 5 31 5 3 02 3 5 16 1 1 51 5 5 4*/}
View Code

 

 

 


 

oj
以后整理。。。

 

 

 

 

 



top


第四章、万能的搜索