这是第一次全部做出来的依次练习了,有一些都是做过两遍了的,但是还是错了几回,更多时候我还是应该多注意下细节,就好像章爷笑我 的一样,像什么vis[]标记没清0,什么格式错误,还有什么题目没看清,还是的注意一下了。

地址:8.1搜索练习

Problem A POJ 2488

A Knight's Journey

题目大意就是说帮你给你个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

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的更多相关文章

  1. 搜索分析(DFS、BFS、递归、记忆化搜索)

    搜索分析(DFS.BFS.递归.记忆化搜索) 1.线性查找 在数组a[]={0,1,2,3,4,5,6,7,8,9,10}中查找1这个元素. (1)普通搜索方法,一个循环从0到10搜索,这里略. (2 ...

  2. [HDU 2102] A计划(搜索题,典型dfs or bfs)

    A计划 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  3. DFS与BFS题解:[kaungbin]带你飞 简单搜索 解题报告

    DFS and  BFS 在解题前我们还是大致讲一下dfs与bfs的.(我感觉我不会bfs) 1.DFS dfs(深度优先算法) 正如其名,dfs是相当的深度,不走到最深处绝不回头的那种. 深度优先搜 ...

  4. 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. ...

  5. 邻接表实现Dijkstra算法以及DFS与BFS算法

    //============================================================================ // Name : ListDijkstr ...

  6. 数据结构(11) -- 邻接表存储图的DFS和BFS

    /////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...

  7. 图论中DFS与BFS的区别、用法、详解…

    DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...

  8. 图论中DFS与BFS的区别、用法、详解?

    DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...

  9. 数据结构基础(21) --DFS与BFS

    DFS 从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到(使用堆栈). //使用邻接矩阵存储的无向图的深度 ...

随机推荐

  1. VC2005从开发MFC ActiveX ocx控件到发布到.net网站的全部过程

      开篇语:最近在弄ocx控件发布到asp.net网站上使用,就是用户在使用过程中,自动下载安装ocx控件.(此文章也是总结了网上好多人写的文章,我只是汇总一下,加上部分自己的东西,在这里感谢所有在网 ...

  2. wx处理鼠标事件

    #include "MainFrame.h" BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_LEFT_DOWN(MyFrame::OnMouseLe ...

  3. pipe()管道最基本的IPC机制

    <h4>进程间通信 fork pipe pie_t 等用法(管道机制 通信)</h4>每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之 ...

  4. 安卓 Dialogs(对话框)

    转载自:http://www.apkbus.com/home.php?mod=space&uid=679028&do=blog&id=61197 对话框是一个小的窗口用以提示用 ...

  5. SmartGit STUDY

    Git Concepts This section helps you to get started with Git and gives you an understanding of the fu ...

  6. GC Buffer Busy Waits处理(转载)

    与单实例不同,在RAC环境中,由于多节点的原因,会因为节点间的资源争用产生GC类的等待,而这其中,GC Buffer Busy Waits又是最为常见的,从性能角度上说,RAC是把双刃剑,用的好,能够 ...

  7. 页面性能测试&提升方式

    性能测试包括:web系统页面测试.web系统后台测试 2种方式来提升你的web 应用程序的速度: ● 减少请求和响应的往返次数 ● 减少请求和响应的往返字节大小. 详细的看此文http://www.5 ...

  8. TCP经受时延的ACK

    下午看<卷1>的时候,感觉“TCP经受时延ACK”这段看的有些迷糊,最后还算理解了,所以这里记下来以免以后又忘了. 经受时延的ACK就是在接收到数据后不立马确认,而是等到内核的一个定时器到 ...

  9. SQLite数据库和JPA简单介绍

    SQLite数据库和JPA简单介绍 一.SQLite简单使用 SQLite是遵循ACID的关系数据库管理系统,它的处理速度很快,它的设计目标是嵌入式的,只需要几百K的内存就可以了. 1.下载SQLit ...

  10. CentOS下安装gns3

    1.安装支持环境 sudo yum intall PyQt4 telnet 2.安装抓包用的wireshark sudo yum install wireshark wireshark-gnome 3 ...