【搜索题目】
来源:互联网 发布:unity3d 安卓包调试 编辑:程序博客网 时间:2024/05/16 01:11
/*POJ 1979 模板题目*/#include<cstdio>#include<cstdlib>#include<cstring>int W,H;char dict[22][22];int sum;bool check(int x,int y){ if(!(x>=1&&x<=H&&y>=1&&y<=W)) return false; return true;}void dfs(int x,int y){ if(!check(x,y)) return ; if(dict[x][y]=='.'||dict[x][y]=='@'){ sum++; dict[x][y]='#'; dfs(x,y-1); dfs(x-1,y); dfs(x,y+1); dfs(x+1,y); }}int main(){ int start_x,start_y; while(~scanf("%d%d",&W,&H)){ if(W==H && W==0) break; for(int i=1;i<=H;i++){ getchar(); for(int j=1;j<=W;j++){ scanf("%c",&dict[i][j]); if(dict[i][j]=='@'){ start_x=i; start_y=j; } } } sum=0; dfs(start_x,start_y); printf("%d\n",sum); }}
/*经典DFS()POJ 3009*/#include<cstdio>#include<cstring>int w,h;//记录场地的宽和高int sx,sy,ex,ey;//记录起点和终点坐标int d[4][2] = { {0,-1}, {1,0}, {0,1}, {-1,0} };//存方向变化量int dict[30][30],best;//best记录最优解。dict存地图void dfs(int cx,int cy,int step){//cx,cy记录当前位置。step表示已走多少步 int nx,ny; if(step>best)//剪枝如果大于目前最优解直接返回 return; for(int i=0;i<4;i++){ nx=cx+d[i][0]; ny=cy+d[i][1]; if(nx>=h||nx<0||ny<0||ny>=w||dict[nx][ny]==1)//越界或立即有阻挡物剪枝 continue; while(nx<h&&nx>=0&&ny<w&&ny>=0&&dict[nx][ny]!=1){//一直滑 if(nx==ex&&ny==ey){//若到终点 if(step+1<best) best=step+1; break; } nx+=d[i][0]; ny+=d[i][1]; } if(nx==ex&&ny==ey)//若由于到终点跳出去 continue; if(nx<h&&nx>=0&&ny<w&&ny>=0){ dict[nx][ny]=0;//若是碰到阻挡物。阻挡物消失。 dfs(nx-d[i][0],ny-d[i][1],step+1);//继续搜索 dict[nx][ny]=1;//还原阻挡物。回溯 } }}int main(){ while(scanf("%d%d",&w,&h),w||h){ best=12;//初始化best for(int i=0;i<h;i++)//读取地图 for(int j=0;j<w;j++){ scanf("%d",&dict[i][j]); if(dict[i][j]==2){ sx=i; sy=j; } if(dict[i][j]==3){ ex=i; ey=j; } } dfs(sx,sy,0);//深搜 if(best<=10) printf("%d\n",best); else printf("-1\n"); }}详细代码
http://blog.csdn.net/bossup/article/details/9014701
/*经典BFS()POJ 3669*/#include<cstdio>#include<queue>#include<algorithm>using namespace std;typedef pair<int ,int >P;const int MAX_M=50000;const int MAX_N=400+1;const int INF=0x7fffffff;//输入int M;int X[MAX_M],Y[MAX_M],T[MAX_M];int dict[MAX_N][MAX_N];//保存地图int d[MAX_N][MAX_N];//保存最短步数int z[4][2] = { {0,-1}, {1,0}, {0,1}, {-1,0} };int bfs(){ if(dict[0][0]==0) return -1; //一开始就被炸 queue<P>que; que.push(P(0,0)); d[0][0]=0; while(!que.empty()){ P p=que.front(); que.pop(); //已到达安全位置 int x=p.first,y=p.second; if(dict[x][y]==INF) return d[x][y]; //4个方向走 for(int i=0;i<4;i++){ int nx=x+z[i][0]; int ny=y+z[i][1]; //判断是否可移动,是否访问过,以及下一个时刻是否安全 if(nx>=0&&ny>=0&&d[nx][ny]==INF&&d[x][y]+1<dict[nx][ny]){ que.push(P(nx,ny)); d[nx][ny]=d[x][y]+1; } } } return -1;}int solve(){ //初始化地图 for(int i=0;i<MAX_N;i++) fill(dict[i],dict[i]+MAX_N,INF); //模拟轰炸场景 for(int i=0;i<M;i++){ dict[X[i]][Y[i]]=min(dict[X[i]][Y[i]],T[i]); for(int j=0;j<4;j++){ int nx=X[i]+z[j][0]; int ny=Y[i]+z[j][1]; if(nx>=0&&ny>=0) dict[nx][ny]=min(dict[nx][ny],T[i]); } } //初始化地图最小步数 for(int i=0;i<MAX_N;i++) fill(d[i],d[i]+MAX_N,INF); //宽度优先搜索 int ans=bfs(); printf("%d\n",ans);}int main(){ scanf("%d",&M); for(int i=0;i<M;i++) scanf("%d %d %d",&X[i],&Y[i],&T[i]); solve();}
详细代码
http://www.cnblogs.com/7hat/p/3595630.html
/*POJ 3187题意:已知有N个数分别为1-N,如下图为4个数。相邻两两相加直至只剩下一个数,下图的结果就是16。 3 1 2 4 4 3 6 7 9 16 现在反过来看,告诉你数的个数N和最终结果,问这N个数的初始序列是什么。求出字典序最小的初始序列。上图的初始序列也可以是3 2 1 4,但这不是字典序最小。分析:这题用全排列的方式非常容易做。首先初始化数组为1-N,然后用STL提供的按字典序生成全排列的函数next_permutation即可枚举全排列。对于每一组数,通过计算可以知道它是否能得出已知结果。最先找到的那组数就是字典序最小的值。*/#include<cstdio>#include<algorithm>using namespace std;const int MAX_N=10;int N,finalsum;int a[MAX_N][MAX_N];int calulate(){//计算序列所得的最后和 for(int i=1;i<N;i++){ for(int j=0;j<N-i;j++){ a[i][j]=a[i-1][j]+a[i-1][j+1]; } } return a[N-1][0];}void solve(){ for(int i=0;i<N;i++)//初始化序列 a[0][i]=i+1; do{//按字典序枚举全排列 int sum=calulate(); if(sum==finalsum){ printf("%d",a[0][0]); for(int i=1;i<N;i++) printf(" %d",a[0][i]); printf("\n"); break; } }while(next_permutation(a[0],a[0]+N));}int main(){ scanf("%d %d",&N,&finalsum); solve(); return 0;}
/*题意:给定一个5*5的地图,每个格子上有一个数字。从一个格子出发(上下左右4个方向),走5步将数字连起来可以构造出一个6位数。问该地图可以构造出多少个不同的6位数。分析:可以对每个格子做深度优先遍历,构造出所有数字,但要注意不要重复计数。在这里,我使用了set来保存已构造出的数字,结果就是set中的元素个数。POJ 3050*/#include<cstdio>#include<set>#include<algorithm>using namespace std;int dict[5][5];set<int>st;int d[4][2] = { {0,-1}, {1,0}, {0,1}, {-1,0} };int dfs(int x,int y,int k,int num){ if(k==6){ st.insert(num); return 0; } for(int i=0;i<4;i++){ int nx=x+d[i][0]; int ny=y+d[i][1]; if(nx>=0&&nx<5&&ny>=0&&ny<5){ k++; dfs(nx,ny,k,num*10+dict[nx][ny]); k--;//回溯 } }}void solve(){ for(int i=0;i<5;i++) for(int j=0;j<5;j++) dfs(i,j,1,dict[i][j]); printf("%d\n",st.size());}int main(){ for(int i=0;i<5;i++) for(int j=0;j<5;j++) scanf("%d",&dict[i][j]); solve();}
/*部分和问题NYOJ 927*/#include<cstdio>int a[25];int n,k;bool dfs(int i,int sum){ if(i==n) return sum==k; if(dfs(i+1,sum)) return true; if(dfs(i+1,sum+a[i])) return true; return false;}int main(){ while(~scanf("%d",&n)){ for(int i=0;i<n;i++) scanf("%d",&a[i]); scanf("%d",&k); if(dfs(0,0)) printf("Of course,I can!\n"); else printf("Sorry,I can't!\n"); }}
/*深搜或者广搜保存上一节点即可NYOJ 20*/#include<cstdio>#include<vector>#include<cstring>using namespace std;const int MAXN=100010;vector<int>Graph[MAXN];int preNode[MAXN];void DFS(int CurNode){ for(int i=0;i<Graph[CurNode].size();i++){ if(preNode[Graph[CurNode][i]])//如果当前节点已经访问过,那么就继续搜索CurNode的下一个邻接点 continue; preNode[Graph[CurNode][i]]=CurNode; DFS(Graph[CurNode][i]); }}void BFS(int CurNode){ int que[MAXN],qs,qe; memset(que,0,sizeof(que)); qe=qs=0; que[qe++]=CurNode; while(qs<qe){ int u=que[qs++]; for(int i=0;i<Graph[u].size();i++){ if(preNode[Graph[u][i]]) continue; preNode[Graph[u][i]]=u; que[qe++]=Graph[u][i]; } }}int main(){ int test; int n,start; int a,b; scanf("%d",&test); while(test--){ scanf("%d%d",&n,&start); memset(Graph,0,sizeof(Graph)); memset(preNode,0,sizeof(preNode)); for(int i=0;i<n-1;i++){ scanf("%d%d",&a,&b); Graph[a].push_back(b);//只要相邻就添加双向边 Graph[b].push_back(a); } preNode[start]=-1; DFS(start); for(int i=1;i<=n;i++) printf("%d ",preNode[i]); }}
/*连连看HDU 1175*/#include<cstdio>#include<queue>using namespace std;#define INT_MAX 0x3f3f3f3fint direc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向依次为右、左、下、上int dict[1005][1005],vis[1005][1005],m,n;//a为输入的2维向量,visited记录该点是否被访问过了,同时记录有转折次数,如果//新的转折次数小于以前访问时的转折次数那么更新,否则就不更新。typedef struct { int x,y,dir,corner;//x,y,为行数列数,dir为方向,corner为转角次数。}node;node start,endx;void bfs(){ queue<node>q; node cur,pre;//用来记录当前的节点和前一个进行比较 start.dir=-1;//开始时无方向 start.corner=0;//开始时转角次数为0 q.push(start); while(!q.empty()){ pre=q.front(); q.pop(); if(pre.x==endx.x&&pre.y==endx.y){ printf("YES\n"); return ; } for(int i=0;i<4;i++){//对节点的四个方向分别进行判断 cur.x=pre.x+direc[i][0]; cur.y=pre.y+direc[i][1]; cur.corner=pre.corner; //令当前转角次数和前一个相同 cur.dir=i; //当前方向 //前一个不能使开始出,且当前方向和前一个方向不一致是转折次数自增1 if(pre.dir!=cur.dir&&pre.dir!=-1) cur.corner++; //判断是否出界,转角次数是否超过限制 if(cur.x<1||cur.y<1||cur.x>n||cur.y>m||cur.corner>2) continue; //如果当前位置有数字存在,且当前位置不是终结位置,违反规则 if(dict[cur.x][cur.y]&&!(cur.x==endx.x&&cur.y==endx.y)) continue; if(cur.corner<vis[cur.x][cur.y]){ vis[cur.x][cur.y]=cur.corner; q.push(cur); } } } printf("NO\n");}int main(){ int q; while(~scanf("%d%d",&n,&m),n,m){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&dict[i][j]); scanf("%d",&q); while(q--){ scanf("%d%d%d%d",&start.x,&start.y,&endx.x,&endx.y); if(start.x==endx.x&&start.y==endx.y) {printf("NO\n"); continue;} //开始和结束在同一个位置 //开始和结束位置没有数字或者开始和结束位置的数字不等。 if(!dict[start.x][start.y]||!dict[endx.x][endx.y]||(dict[start.x][start.y]!=dict[endx.x][endx.y])) {printf("NO\n"); continue;} for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) vis[i][j]=INT_MAX; bfs(); } }}
0 0
- 【搜索题目】
- POJ搜索题目总结
- POJ搜索题目
- POJ搜索题目汇总
- 搜索专题题目推荐
- POJ 搜索题目分类
- 《有关搜索题目》
- ACM搜索题目总结
- poj搜索题目
- poj 搜索题目列表
- poj搜索题目分类
- 数据结构上机题目--搜索
- POJ 搜索题目分类
- ACM搜索题目总结
- 搜索题目集合
- acm,关于搜索题目
- 二分搜索经典题目
- 题目:搜索二维矩阵
- 设计模式之策略模式
- 再解java中的String
- for命令笔记
- Java nio
- 博客推广外链接-SEO搜索引擎优化
- 【搜索题目】
- ubuntu下Banshee播放器安装Douban插件+OSD Lyrics
- python -----example
- 冒泡排序
- NYOJ 136 等式
- 插入排序
- 归并排序
- 堆排序
- javascript学习笔记