您的位置:首页 > 其它

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

一个简单又基础的搜索题目:

#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
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
  

s
+
|+
|
+e
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: