训练一 深度优先搜索

例1.  POJ 1979 Red and Black
题意:由@为起点,周围最多有‘ . ’跟它相连通,不能越过‘ # ’。@本身也算一个
输入输出
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13

代码:
#include<iostream>
using namespace std;
char map[25][25];
int n,m,num;
int i,j,ii,jj;
int dfs(int x,int y)
{
int i;
if(map[x+1][y]=='#'&&map[x-1][y]=='#'&&map[x][y+1]=='#'&&map[x][y-1]=='#')
{
return 0;
}
if(x<=n&&y<=m)
{
if(x+1<=n&&map[x+1][y]!='#')
{
num++;
map[x+1][y]='#';
dfs(x+1,y);
}
if(x-1>0&&map[x-1][y]!='#')
{
num++;
map[x-1][y]='#';
dfs(x-1,y);
}
if(y+1<=m&&map[x][y+1]!='#')
{
num++;
map[x][y+1]='#';
dfs(x,y+1);
}
if(y-1>0&&map[x][y-1]!='#')
{
num++;
map[x][y-1]='#';
dfs(x,y-1);
}
}
return 1;
}
int main()
{
while(cin>>m>>n&&m*n!=0)
{
if(m*n)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='@')
{
ii=i;
jj=j;
}
}
}
for(j=0;j<=n+1;j++)
{
map[j][0]='#';
map[j][m+1]='#';
}
for(j=0;j<=m+1;j++)
{
map[0][j]='#';
map[n+1][j]='#';
}
num=1;
map[ii][jj]='#';
dfs(ii,jj);
cout<<num<<endl;
}
else
cout<<0<<endl;
}
return 0;
}

思路:以@为起点上下左右四个方向搜索,到一个点计数器加1,把‘ . ’改为‘ # ’。当走到四周都为‘#’时,搜索结束。









例二: hdu  1010  Tempter of the Bone
题意:

在一张地图上,给定起点和终点,问能否恰好在t时刻到达终点


 没有过的代码
#include<iostream>
#include<cstring>
#define N 10
using namespace std;
char mapp[N][N];
bool visited[N][N],flag;
int dic[4][2]={1,0,-1,0,0,1,0,-1};
int n,m,t,end_i,end_j;
int abs(int a,int b)
{
    if(a<b) return b-a;
    else return a-b;
}
void  DFS(int i,int j,int c)
{
 int u,w,k;
 if(flag)return;
 if(c>t)return;
 if(i<0||i>=n||j<0||j>=m)return;
 if(mapp[i][j]=='D')
 {
  if(c==t)
  {
   flag=true;
  }
  return ;
 }
 int temp=abs(i,end_i)+abs(j,end_j);
    temp=t-temp-c;
 if(temp&1)
 return ;
 for(k=0;k<4&&!flag;k++)
 {
  u=i+dic[k][0];
  w=j+dic[k][1];
   if(mapp[u][w]!='X')
   if(visited[u][w]==false)
   {
    visited[u][w]==true;
    DFS(u,w,c+1);
    visited[u][w]==false;
    if(flag)
    return;
   }
  
  } 
}
int main()
{
 int i,j,k,x,y;
  while(cin>>m>>n>>t&&(m||n||t))
  {
   k=0;
   memset(visited,false,sizeof(visited));
  for(i=0;i<n;i++)
  {
  for(j=0;j<m;j++)
  {
  cin>>mapp[i][j];
  if(mapp[i][j]=='D')
  {
   end_i=i;
   end_j=j;
  }
   if(mapp[i][j]=='S')
  {
   visited[i][j]=true;
   x=i;
   y=j;
  }
  if(mapp[i][j]=='X')
   k++;
  }
 }
 flag=false;
 if(m*n-k-1>=t)
  DFS(x,y,0);
  if(flag)
   cout<<"YES"<<endl;
  else
   cout<<"NO"<<endl;
 }
 return 0;
}


过的代码

#include<iostream>
#include<cstring>
#define N 10
using namespace std;
char mapp[N][N];
bool visited[N][N],flag;
int dic[4][2]={1,0,-1,0,0,1,0,-1};
int n,m,t,end_i,end_j;
int abs(int a,int b)
{
    if(a<b) return b-a;
    else return a-b;
}
void  DFS(int i,int j,int c)
{
 int u,w,k;
 if(flag)return;
 if(c>t)return;
 if(i<0||i>=n||j<0||j>=m)return;
 if(mapp[i][j]=='D')
 {
  if(c==t)
  {
   flag=true;
  }
  return ;
 }
 int temp=abs(i,end_i)+abs(j,end_j);
    temp=t-temp-c;
 if(temp&1)
 return ;
  if(!visited[i-1][j]&&mapp[i-1][j]!='X')
    {
        visited[i-1][j]=true;
        DFS(i-1,j,c+1);
        visited[i-1][j]=false;
    }
    if(!visited[i+1][j]&&mapp[i+1][j]!='X')
    {
        visited[i+1][j]=true;
        DFS(i+1,j,c+1);
        visited[i+1][j]=false;
    }
    if(!visited[i][j-1]&&mapp[i][j-1]!='X')
    {
        visited[i][j-1]=true;
        DFS(i,j-1,c+1);
        visited[i][j-1]=false;
    }
    if(!visited[i][j+1]&&mapp[i][j+1]!='X')
    {
        visited[i][j+1]=true;
        DFS(i,j+1,c+1);
        visited[i][j+1]=false;
    } 
}
int main()
{
 int i,j,k,x,y;
  while(cin>>m>>n>>t&&(m||n||t))
  {
   k=0;
   memset(visited,false,sizeof(visited));
  for(i=0;i<n;i++)
  {
  for(j=0;j<m;j++)
  {
  cin>>mapp[i][j];
  if(mapp[i][j]=='D')
  {
   end_i=i;
   end_j=j;
  }
   if(mapp[i][j]=='S')
  {
   visited[i][j]=true;
   x=i;
   y=j;
  }
  if(mapp[i][j]=='X')
   k++;
  }
 }
 flag=false;
 if(m*n-k-1>=t)
  DFS(x,y,0);
  if(flag)
   cout<<"YES"<<endl;
  else
   cout<<"NO"<<endl;
 }
 return 0;
}

思路:DFS+减枝,奇偶剪枝

第一个剪枝我们可以想到,当剩下的步数大于剩下的时间的时候,狗是不能走到的;
 
接下来我们来第二个剪枝:
我们把map的奇偶性以01编号:
0 1 0 1 0 1 
1 0 1 0 1 0 
0 1 0 1 0 1 
1 0 1 0 1 0 
0 1 0 1 0 1 
我们发现从0走一步一定走到1,从1走一步一定走到0。
也就是说,如果当前的狗所在的坐标与D的坐标奇偶性不一样,那么狗需要走奇数步。
同理,如果狗所在坐标与D的坐标奇偶性一样,那么狗需要走偶数步数。
 
也就是说,狗的坐标x、y和对2取余是它的奇偶性,Dxy和对2取余是D的奇偶性。
两个奇偶性一加再对2取余,拿这个余数去与剩下时间对2取余的余数作比较即可。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值