25号搜索的一些例子,。。Oil Deposits&&Red and Black&&Knight Moves&&Catch That Cow&&Tempter of the Bone
2013-07-25 23:27
525 查看
Oil Depositshttp://poj.org/problem?id=1562
一个简单又基础的搜索题目:
Red and Blackhttp://poj.org/problem?id=1979
Knight Moveshttp://poj.org/problem?id=2243
前面三个题目都可以用bfs()来计算,但前俩种有简便的方法。
思路:国际上的Knight Move是走”日子“形的(常识)。
这是最基础的模板!
Catch That Cowhttp://poj.org/problem?id=3278
好像是最简单的一道搜索题,但仍有难度的!
Tempter of the Bonehttp://acm.fafu.edu.cn/problem.php?id=1167
用Dfs()来求解,首先要考虑不能到达的情况。。。
这题那个i不能乱定义!,所以变量的定义以及范围也要注意!
奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
一个简单又基础的搜索题目:
#include<iostream> #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; char a[105][105]; int s=0,i,j,x,y;“有多个函数,应把变量定义在外面”深搜 void dfs(int i,int j) { if(i<1||i>x||j<1||j>y||a[i][j]!='@') return ;//直接跳出来. else {a[i][j]='!'; dfs(i-1,j); dfs(i-1,j-1); dfs(i,j-1); dfs(i,j+1); dfs(i+1,j+1); dfs(i-1,j+1); dfs(i+1,j); dfs(i+1,j-1);} } int main() { int i,j; while(scanf("%d %d",&x,&y)!=EOF) { if(x==0||y==0) break; s=0; for(i=1;i<=x;i++) for(j=1;j<=y;j++) cin>>a[i][j];。。。不能用scanf来输入(不清楚。) for(i=1;i<=x;i++) for(j=1;j<=y;j++) { if(a[i][j]=='@') { dfs(i,j); s++; } } printf("%d\n",s); } return 0; }
Red and Blackhttp://poj.org/problem?id=1979
#include<iostream> #include<queue> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std ; char a[200][200]; int x,y,s=0,i,j,n,m; void dfs(int i,int j) { if(i<1||i>y||j<1||j>x||a[i][j]!='.') return ; else { s++; a[i][j]='@'; dfs(i+1,j); dfs(i-1,j); dfs(i,j+1); dfs(i,j-1); } } int main() { while(scanf("%d%d",&x,&y)!=EOF) { s=0; if(x==0||y==0) break; for(i=1;i<=y;i++) 31 { 32 scanf("%s",a[i]+1); 33 }//行列的转化,用字符串数组来进行输入 for(i=1;i<=y;i++) for(j=1;j<=x;j++) { if(a[i][j]=='@') { a[i][j]='.'; n=i; m=j; break; } } dfs(n,m); printf("%d\n",s); } return 0; }
Knight Moveshttp://poj.org/problem?id=2243
前面三个题目都可以用bfs()来计算,但前俩种有简便的方法。
思路:国际上的Knight Move是走”日子“形的(常识)。
这是最基础的模板!
#include<iostream> #include<queue> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std ; int sx,sy,ex,ey,map[10][10]; int dir[8][2]={{-2,-1}, {-2,1}, {-1,-2}, {-1, 2},{1,-2}, {1,2}, {2,-1}, {2,1}};//注意枚举来表示 int bfs()//广搜要用到队列 { int i,x1,y1,x2,y2; memset(map,0,sizeof(map)); queue<int>Q ; Q.push(sx); Q.push(sy); while(Q.empty()==0) { x1=Q.front(); Q.pop() ; y1=Q.front(); Q.pop() ; if(x1==ex && y1==ey) { return map[x1][y1]; } for(i=0;i<8;i++) { x2=x1+dir[i][0]; y2=y1+dir[i][1]; if( x2>0 && x2<=8 && y2>0 && y2<=8 && map[x2][y2]==0) { map[x2][y2]=map[x1][y1]+1; Q.push(x2); Q.push(y2); } } } } int main() { while(scanf("%c%d %c%d%*c//什么情况",&sx,&sy,&ex,&ey)!=EOF) { sx=sx-'a'+1; ex=ex-'a'+1;//变换 printf("To get from %c%d to %c%d takes %d knight moves.\n",sx+'a'-1,sy,ex+'a'-1,ey,bfs()); } return 0; }
Catch That Cowhttp://poj.org/problem?id=3278
好像是最简单的一道搜索题,但仍有难度的!
#include<stdio.h> #include<string.h> #include<iostream> #include<queue> using namespace std; int map1[200005]; int a,b; int a1[4]={1,1,2},b1[4]={1,-1,0}; int bfs() { int k,k1,i; memset(map1,0,sizeof(map1)); queue<int> Q; Q.push(a); while(Q.empty()==0) { k=Q.front(); Q.pop(); if(k==b) { return map1[k]; } for(i=0;i<3;i++) { k1=k*a1[i]+b1[i]; if(k1>=0&&k1<=200000&&map1[k1]==0) { map1[k1]=map1[k]+1; Q.push(k1); } } } } int main() { while(scanf("%d %d",&a,&b)!=EOF) printf("%d\n",bfs()); return 0; }
Tempter of the Bonehttp://acm.fafu.edu.cn/problem.php?id=1167
用Dfs()来求解,首先要考虑不能到达的情况。。。
这题那个i不能乱定义!,所以变量的定义以及范围也要注意!
#include<iostream> #include<stdio.h> #include<algorithm> #include<math.h> using namespace std; char a[7][7]; int w[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int x,y,t,n,m,n1,m1,flag; void dfs(int n,int m,int time) { int n2,m2,i;//变量的定义 if(n==n1&&m==m1&&time==t) flag=1; if(time>t) return ; if(flag) return ; if((t-time)%2!=(abs(n-n1)+abs(m-m1))%2)//奇偶剪枝((t-time-abs(n-n1)-abs(m-m1))%2!=0) return ; for(i=0;i<4;i++) { n2=n+w[i][0]; m2=m+w[i][1]; if(n2>=0&&n2<x&&m2>=0&&m2<y) { if(a[n2][m2]!='X') { a[n2][m2]='X'; dfs(n2,m2,time+1); a[n2][m2]='.';//回溯法 } } } } int main() { int k,i,j;//变量的定义 while(scanf("%d%d%d",&x,&y,&t)!=EOF) { k=0; if(x==0&&y==0&&t==0) break; for(i=0;i<x;i++) scanf("%s",a[i]); for(i=0;i<x;i++) for(j=0;j<y;j++) { if(a[i][j]=='S') { n=i; m=j; a[i][j]='X'; } if(a[i][j]=='D') { n1=i; m1=j; k++; } if(a[i][j]=='.') k++; } if(k<t) { printf("NO\n"); continue; } flag=0; dfs(n,m,0); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
相关文章推荐
- hdu - 1010 Tempter of the Bone (dfs+奇偶性剪枝) && hdu-1015 Safecracker(简单搜索)
- ZOJ2110 HDU1010 搜索 Tempter of the Bone
- 【搜索-DFS】hdu1010 Tempter of the Bone
- HDU 1010 Tempter of the Bone (深度搜索+减枝优化)
- HDU 1010 Tempter of the Bone(搜索经典题)
- HDU-1010-Tempter of the Bone(搜索奇偶剪枝)
- HDU 1010 && ZOJ 2110--Tempter of the Bone【DFS && 奇偶剪枝】
- 【搜索】 HDU 2128 Tempter of the Bone II BFS 状压
- SDAU 搜索专题 18 Tempter of the Bone
- HDU 1010 Tempter of the Bone (搜索 + 奇偶剪枝)
- 【搜索】 HDU 2128 Tempter of the Bone II BFS 状压
- HDOJ 1010 Tempter of the Bone(搜索,奇偶剪枝)
- hdu-1010-Tempter of the Bone(搜索 优化)
- HDU 1010 Tempter of the Bone 搜索 奇偶剪枝
- 1010 Tempter of the Bone 深度搜索 奇偶剪枝
- E - Tempter of the Bone(深度搜索)
- hdu 1010 Tempter of the Bone(搜索)
- ZOJ2110 HDU1010 搜索 Tempter of the Bone
- FOJ--1046--Tempter of the Bone--解题报告(典型的迷宫搜索)
- zoj2110 Tempter of the Bone 搜索dfs