第一节、深度优先搜索
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; }
为了深入了解深搜,用两个方法改变程序:
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; }
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; }
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; }
#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; }
第二节、解救小哈
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 4 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 4 3 */
第三节、广度优先搜索
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 4 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 1 4 3 */
第四节、再解炸弹人
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# ############# */
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# ############# */
第五节、宝岛探险
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 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 */
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 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 */
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 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 */
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 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 */
第六节、水管工游戏
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 4 5 3 5 3 1 5 3 0 2 3 5 1 6 1 1 5 1 5 5 4 */
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 4 5 3 5 3 1 5 3 0 2 3 5 1 6 1 1 5 1 5 5 4 */ }
oj
以后整理。。。
top
时间: 2024-10-17 21:42:31