8.1搜索专练DFS和BFS
这是第一次全部做出来的依次练习了,有一些都是做过两遍了的,但是还是错了几回,更多时候我还是应该多注意下细节,就好像章爷笑我 的一样,像什么vis[]标记没清0,什么格式错误,还有什么题目没看清,还是的注意一下了。
地址:8.1搜索练习
Problem A POJ 2488
题目大意就是说帮你给你个P*Q的棋盘,让马一次全部走完,每个点只能走一次,而且要按照字典序输出(这句话最坑!!!)。
这道题做过了两三次了,却老是被那句“字典序输出”给坑死。第一次看到这道题的时候,看到他说的字典序还以为是要让起点最小(虽然现在明白任何一个点作为起点都是可以到达终点的,只要里面有一条路可以遍历完),然后高高兴兴的枚举了起点,心想好简单叽里呱啦就敲完了,测试样例!过了!提交!WA了!然后就回头看代码,检查实在是无力了,在网上一搜,发现别人只用0,0,做起点就过了,马上改了提交!!!还是WA!!心力憔悴的我无力了,有重新找别人的代码,看到别人代码原来还有一小段注释
“int dir[8][2]={-2,-1,-2,1,-1,-2,-1,2,1,-2,1,2,2,-1,2,1}; /*注意此处的数组数据, 为了保证每次的探索都是 符合字典序的*/”
然后才慢慢明白什么叫字典序输出,其实就是要让每一步走的位置要是在能够遍历每个点的前提下,尽量让字典序小。大家可以慢慢体会下。
贴代码:180 KB 16 ms
- #include <stdio.h>
- #include <string.h>
- int vis[][];
- const int d[][] = {{-,-},{-,},{-,-},{-,},{,-},{,},{,-},{,}};
- int m,n,num,ans[],IsFind;
- void dfs(int x,int y)
- {
- if(x< || x>=m || y< || y>=n || vis[x][y] || IsFind) return ;
- vis[x][y] = ;
- ans[num++] = x*n+y;
- if(num == m*n){IsFind = ; return;}
- for(int i=;i< && !IsFind;i++)
- {
- dfs(x+d[i][], y+d[i][]);
- }
- if(!IsFind)
- {
- num--;
- vis[x][y]=;
- }
- }
- int main()
- {
- int Case,T=;
- while(~scanf("%d", &Case))while(Case--)
- {
- memset(vis,,sizeof(vis));
- scanf("%d%d", &n, &m);
- IsFind = ;
- num=;
- dfs(,);
- printf("Scenario #%d:\n", ++T);
- if(!IsFind)printf("impossible");
- else for(int i=;i<num;i++)
- {
- printf("%c%d", ans[i]/n+'A', ans[i]%n+);
- }
- printf("\n\n");
- if(!Case)T=;
- }
- return ;
- }
Problem B Avoid The Lakes
简单的DFS求最大相连块 392 KB 16 ms
- #include <stdio.h>
- #include <string.h>
- #include <queue>
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- using namespace std;
- const int d[][] = {{-,},{,},{,-},{,}};
- int N,M,K;
- int Map[][],vis[][];
- int DFS(int x,int y)
- {
- if(x< || x>=N || y< || y>=M || vis[x][y] || Map[x][y])return ;
- int area = ;
- vis[x][y] = ;
- for(int i=;i<;i++)
- {
- area += DFS(x+d[i][], y+d[i][]);
- }
- return area;
- }
- int main()
- {
- while(~scanf("%d%d%d",&N,&M,&K))
- {
- memset(Map,,sizeof(Map));
- memset(vis,,sizeof(vis));
- int a,b;
- for(int i=;i<K;i++)
- {
- scanf("%d%d", &a,&b);
- Map[a-][b-] = ;
- }
- int ans = ;
- for(int i=;i<N;i++)
- {
- for(int j=;j<M;j++)if(!vis[i][j] && !Map[i][j])
- {
- int temp = DFS(i,j);
- ans = MAX(ans, temp);
- }
- }
- printf("%d\n", ans);
- }
- return ;
- }
Problem C Dungeon Master
只是将求最短距离从二维增加到三维而已,数组加一维便可以实现436 KB16 ms
- #include <cstdio>
- #include <cstring>
- #include <queue>
- using namespace std;
- const int Dir[][] = {{,,},{,,-},{,,},{,-,},{,,},{-,,}};
- struct node
- {
- int x,y,z;
- int step;
- }Start;
- char Map[][][];
- int vis[][][];
- int L,R,C;
- void readData()
- {
- memset(vis,,sizeof(vis));
- int IsFind_S=;
- for(int i=;i<L;i++)
- {
- for(int j=;j<R;j++)
- {
- scanf("%s",Map[i][j]);
- for(int k=;k<C && !IsFind_S;k++) if(Map[i][j][k] == 'S')
- {
- Start.x = i;
- Start.y = j;
- Start.z = k;
- vis[i][j][k] = ;
- Start.step = ;
- IsFind_S = ;
- }
- }
- }
- }
- int BFS()
- {
- queue<node>q;
- q.push(Start);
- while(!q.empty())
- {
- node u = q.front();
- q.pop();
- int x = u.x, y = u.y, z = u.z;
- if(Map[x][y][z] == 'E')return u.step;
- for(int i=;i<;i++)
- {
- int nx = x + Dir[i][], ny = y + Dir[i][], nz = z + Dir[i][];
- if(nx>= && nx<L && ny>= && ny<R && nz>= && nz < C && Map[nx][ny][nz]!='#' && !vis[nx][ny][nz])
- {
- vis[nx][ny][nz] = ;
- node v;
- v.x = nx; v.y = ny; v.z = nz; v.step = u.step+;
- q.push(v);
- }
- }
- }
- return ;
- }
- int main()
- {
- while(scanf("%d%d%d%*c", &L, &R, &C) && (L||R||C))
- {
- readData();
- int ans = BFS();
- if(!ans)printf("Trapped!\n");
- else printf("Escaped in %d minute(s).\n",ans);
- }
- return ;
- }
Problem D Sum It Up
题目意思就是说给一个T和N个数,让你求出所有的可以让N个数里面找出一些数使得他们的和为T,求所有情况
由于题目说了每给一个数,这个数就只能用一次,就是说帮你给20,20,20,那么你可以用1个,2个或者3个20,但是你只用第1个或者只用第2个这两种情况都是一样的。这样的话我们每次储存时候就不要重复的储存每个数,而是另外开一个数组保存每个不一样的数,在开一个数组保存每个数的次数。那么在DFS的时候就按照每个不同的数出现的次数,从max~0一直到他们的和为T,就打印数组
代码里还有注释:228 KB 0 ms
- #include <stdio.h>
- #include <string.h>
- #include <queue>
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- using namespace std;
- int ans[];
- int N,T,IsFind;
- int use[],num[],NumOfUse;//NumOdUse用来统计有多好个不同的数,Use放的是不同的数,num放的是每个不同的数出现的次数
- int index,k;//index表示DFS到了use[index],ans总共有k个数
- void DFS(int sum)
- {
- if(sum > T)return ;//和已经大于目标值,不需要继续搜索下去了
- if(sum == T)//找到了就打印出来
- {
- IsFind = ;//找到了
- for(int i=;i<k;i++)//打印
- {
- printf("%d%c", ans[i], (i==k-)? '\n' : '+');
- }
- return ;
- }
- if(index == NumOfUse)return;//已经找到了最后一个,任然不满足,返回
- for(int i=num[index];i>=;i--)//对于第num[index],枚举他出现的次数
- {
- for(int j=;j<i;j++)ans[k+j] = use[index];//向ans里放入i个数
- index+=;k+=i;
- DFS(sum+use[index-]*i);
- index-=;k-=i;
- }
- }
- int main()
- {
- while(~scanf("%d%d", &T,&N) && N)
- {
- memset(num,,sizeof(num));
- memset(ans,,sizeof(ans));
- memset(use,,sizeof(use));
- scanf("%d", &use[]);
- num[] = ;
- NumOfUse = ;
- int temp;
- for(int i=;i<N;i++)
- {
- scanf("%d", &temp);
- if(temp == use[NumOfUse-])num[NumOfUse-]++;//由于题目保证输入时非升序,所以直接与前一个比较,相同,次数加1
- else {use[NumOfUse] = temp; num[NumOfUse]++;NumOfUse ++;}//不同,数的个数加1
- }
- IsFind = ;
- printf("Sums of %d:\n",T);
- DFS();
- if(!IsFind)printf("NONE\n");
- }
- return ;
- }
Problem E N皇后问题
第一次,直接用白书的方法,超时
- #include <stdio.h>
- #include <string.h>
- int vis[][],ans,n;
- void dfs(int cur)
- {
- if(cur == n){ans++;return;}
- for(int i=;i<n;i++)
- {
- if(!vis[][i] && !vis[][i+cur] && !vis[][cur-i+n])
- {
- vis[][i] = vis[][i+cur] = vis[][cur-i+n] = ;
- dfs(cur+);
- vis[][i] = vis[][i+cur] = vis[][cur-i+n] = ;
- }
- }
- }
- int main()
- {
- while(~scanf("%d", &n) && n)
- {
- ans = ;
- memset(vis,,sizeof(vis));
- dfs();
- printf("%d\n", ans);
- }
- return ;
- }
第二次,听了章爷的说法,打表,没有写 if(!n)break;WA了
- #include <stdio.h>
- #include <string.h>
- int ans[] = {,,,,,,,,,,};
- int main()
- {
- int n;
- while(~scanf("%d", &n))
- {
- printf("%d\n",ans[n]);
- }
- return ;
- }
第三次,终于过了228 KB15 ms
- #include <stdio.h>
- #include <string.h>
- int ans[] = {,,,,,,,,,,};
- int main()
- {
- int n;
- while(~scanf("%d", &n) && n)
- {
- printf("%d\n",ans[n]);
- }
- return ;
- }
Problem F Basic
此题我没有加入太多想法,有思路就敲了,所以写得有些挫,代码效率也不高,基本思路就是枚举每个点是否放上一个棋子,共有2^16种情况,然后就没放上一个就标记之后不能放上的点,找出者2^16中情况中可以放得数目最多的
其实也可以直接枚举每个点,放或者不放两种情况,搜索下一个点
代码 172 KB63 ms
- #include <stdio.h>
- #include <string.h>
- #include <queue>
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- using namespace std;
- int N;
- char Map[][],vis[][];
- const int d[][] = {{-,},{,},{,-},{,}};
- int main()
- {
- while(~scanf("%d", &N) && N)
- {
- for(int i=;i<N;i++)
- {
- scanf("%s", Map[i]);
- }
- int Max = ;
- for(int state = ;state < (<<(N*N));state++)
- {
- memset(vis,,sizeof(vis));
- int ans = ;
- for(int i=;i<(N*N);i++)
- {
- if(((<<i) & state) && Map[i/N][i%N]!='X' && !vis[i/N][i%N])
- {
- ans++;
- vis[i/N][i%N] = ;
- for(int k=;k<;k++)
- {
- int x = i/N +d[k][], y = i%N+d[k][];
- while(x>= && x<N && y>= && y<N && Map[x][y]!='X')
- {
- vis[x][y] = ;
- x+=d[k][]; y += d[k][];
- }
- }
- }
- }
- Max = MAX(Max, ans);
- }
- printf("%d\n", Max);
- }
- return ;
- }
Problem GAsteroids!
简单的三维BFS问题
- #include <stdio.h>
- #include <string.h>
- #include <queue>
- #define Is(a,b) (a>=0 && a<b)
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- using namespace std;
- const int Dir[][] = {{,,},{-,,},{,,},{,-,},{,,},{,,-}};
- int vis[][][],N;
- struct node{int x,y,z,step;};
- node Start,End;
- char Map[][][];
- int ReadData()
- {
- memset(Map, , sizeof(Map));
- char str[]={};
- scanf("%s %d%*c", str, &N);
- for(int i=;i<N;i++)
- {
- for(int j=;j<N;j++)
- {
- scanf("%s", Map[i][j]);
- }
- }
- int x,y,z;
- scanf("%d%d%d",&x,&y,&z);
- Start.x = z; Start.y = y; Start.z = x;
- scanf("%d%d%d",&x,&y,&z);
- End.x = z; End.y = y; End.z = x;
- scanf("%s",str);
- if(str[] == 'E')return ;
- return ;
- }
- int BFS()
- {
- memset(vis, , sizeof(vis));
- queue<node>q;
- Start.step = ;
- q.push(Start);
- node u, v;
- vis[Start.x][Start.y][Start.z] = ;
- while(!q.empty())
- {
- u = q.front();
- q.pop();
- int x = u.x, y = u.y, z = u.z;
- if(x == End.x && y == End.y && z == End.z)return u.step;
- for(int i=;i<;i++)
- {
- int nx = x+Dir[i][], ny = y+Dir[i][], nz = z+Dir[i][];
- if(Is(nx,N) && Is(ny,N) && Is(nz, N) && !vis[nx][ny][nz] && Map[nx][ny][nz]!='X')
- {
- vis[nx][ny][nz] = ;
- v.x = nx; v.y = ny; v.z = nz;
- v.step = u.step+;
- q.push(v);
- }
- }
- }
- return -;
- }
- int main()
- {
- while(ReadData())
- {
- int ans = BFS();
- if(ans == -)printf("NO ROUTE\n");
- else printf("%d %d\n",N,ans);
- }
- }
8.1搜索专练DFS和BFS的更多相关文章
- 搜索分析(DFS、BFS、递归、记忆化搜索)
搜索分析(DFS.BFS.递归.记忆化搜索) 1.线性查找 在数组a[]={0,1,2,3,4,5,6,7,8,9,10}中查找1这个元素. (1)普通搜索方法,一个循环从0到10搜索,这里略. (2 ...
- [HDU 2102] A计划(搜索题,典型dfs or bfs)
A计划 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- DFS与BFS题解:[kaungbin]带你飞 简单搜索 解题报告
DFS and BFS 在解题前我们还是大致讲一下dfs与bfs的.(我感觉我不会bfs) 1.DFS dfs(深度优先算法) 正如其名,dfs是相当的深度,不走到最深处绝不回头的那种. 深度优先搜 ...
- Clone Graph leetcode java(DFS and BFS 基础)
题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...
- 邻接表实现Dijkstra算法以及DFS与BFS算法
//============================================================================ // Name : ListDijkstr ...
- 数据结构(11) -- 邻接表存储图的DFS和BFS
/////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...
- 图论中DFS与BFS的区别、用法、详解…
DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...
- 图论中DFS与BFS的区别、用法、详解?
DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...
- 数据结构基础(21) --DFS与BFS
DFS 从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到(使用堆栈). //使用邻接矩阵存储的无向图的深度 ...
随机推荐
- php数组排序函数
下边提到的几个数组函数的排序有一些共性: 1 数组被作为排序函数的参数,排序以后,数组本身就发生了改变,函数的返回值为bool类型.2 函数名中出现单a表示association,含义为,在按值排序的 ...
- (转)gLFlush()和gLFinish()
笔者初使用OpenGL之时,所遇到的命令不能生效的问题:比如开始想用gLClearColor来设置背景色为红色,结果执行后背景还是默认的黑色.后来查阅资料,才知道这与OpenGL的指令执行流程有关,要 ...
- Linux Shell编程(4): 逻辑运算符、逻辑表达式详解
shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决我们很多复杂的判断,达到事半功倍效果. 一.逻辑运算符 逻辑卷标 表示意思 1. 关于档案与目录的侦测逻辑卷标! -f 常用!侦测 ...
- 【英语】Bingo口语笔记(55) - work系列
- oracle----sqlldr用法
SQL*LOADER是ORACLE的数据加载工具,通常用来将操作系统文件迁移到ORACLE数据库中.SQL*LOADER是大型数据仓库选择使用的加载方法,因为它提供了最快速的途径(DIRECT,PAR ...
- http报头正文开头会有一个整数的问题
HTTP/.0 200 OK (省略一些东西...) Content-type:text/html 正文内容 这是我用Arduino访问某个php得到的结果 如果我在php里头输出1000个字符或更少 ...
- 设置VMWARE通过桥接方式使用主机无线网卡上网(zz)
环境:WIN7旗舰版,台式机,U盘无线上网卡. 虚拟软件:VMware9.0,虚拟系统:CentOS6.4 需要实现虚拟机以独立机形式工作和上网. 先介绍一下VMware网络设置的三种方式 1 Hos ...
- cocos2dx+lua中cc.EventListenerMouse:create()的bug
今天在调试项目的时候用到了鼠标事件的监听 在创建事件监听器的时候出了问题 cc.EventListenerMouse:create() 这句返回值为nil 原来这是cocos2dx引擎的一个bug,t ...
- IOS设备启动图像命名规范
- SQL 教程学习进度备忘
书签:跳过:另外跳过的内容有待跟进 __________________ 学习资源:W3School. _________________ 跳过的内容: 1. “SQL select”底部的“ AD ...