码迷,mamicode.com
首页 > 其他好文 > 详细

搜索题解

时间:2020-01-23 14:06:16      阅读:81      评论:0      收藏:0      [点我收藏+]

标签:nod   std   sizeof   getc   turn   mes   bre   个人   i++   

1.Oil Deposits

  bfs,遍历每个满足条件的点,找到附近满足条件的点,再从这个点周围继续找点。

https://vjudge.net/problem/HDU-1241

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 105
char map[N][N];
bool vis[N][N];//标记的点
struct node
{ int x,y;
};
queue<node> q;
int fx[8]={1,0,-1,0,-1,1,-1,1},fy[8]={0,1,0,-1,1,-1,-1,1};
void bfs(int x,int y)
{ q.push({x,y});
 int nx,ny,i;
 while(q.size())
 { node now = q.front();
  q.pop();
  for(i=0;i<8;i++)//往满足条件的点周围的八个方向找点,满足条件就放入队列。
  { nx=now.x+fx[i];
   ny=now.y+fy[i];
   if(!vis[nx][ny]&&map[nx][ny]==@&&nx>=0&&nx<100&&ny>=0&&ny<100)
   { q.push({nx,ny});
    vis[nx][ny]=1;
   }
  }
 }
}
int main()
{ int m,n,i,j,sum;
 while(~scanf("%d %d",&n,&m))
 { if(n==0&&m==0)
   break;
   else
  { sum=0;
    getchar(); 
    memset(map,0,sizeof map);
    memset(vis,0,sizeof vis);
    for(i=0;i<n;i++)
  { for(j=0;j<m;j++)
   scanf("%c",&map[i][j]);
   getchar();
  }
  for(i=0;i<n;i++)
  { for(j=0;j<m;j++)
   { if(map[i][j]==@&&vis[i][j]==0)//从满足条件的点开始搜索,找到这个点周围的点并标记。
    { bfs(i,j);
      sum++;
    }
   }
  }
  printf("%d\n",sum);
  }
 }
 return 0;
}

2.迷宫问题

https://vjudge.net/problem/OpenJ_Bailian-4127

用广度搜索,但是输出就不好搞,我们在创建队列结构体时,还要多创建一个变量用来记录这个点的根节点,这里我用了一个单独的函数输出,如果这个点不不是根节点,就递归并输出这个点,这样就能实现倒叙输出位置了。

#include<stdio.h>
#include<string.h>
#define n 5
using namespace std;
bool vis[n][n];//标记地图
int map[n][n]={0};
int fx[4]={0,1,0,-1};
int fy[4]={1,0,-1,0};
struct node
{ int x,y;
 int pre;
}q[100];
void print(int last)//递归输出这个点的上一个节点,直到根节点位置
{ if(q[last].pre!=last)
 print(q[last].pre);
 printf("(%d, %d)\n",q[last].x,q[last].y);//递归后仍需输出这个点的坐标
}
int main()
{ int i=0,j=0,x,y;
 for(i=0;i<n;i++)
 for(j=0;j<n;j++)
 scanf("%d",&map[i][j]);
 vis[0][0]=1;
 int nx,ny,flag=0;
 q[0].x=0;
 q[0].y=0;
 q[0].pre=0;
 memset(vis,0,sizeof vis);
 int front=0,last=1;
 while(front<last)
 { 
  for(i=0;i<4;i++)
 { nx=q[front].x+fx[i];
  ny=q[front].y+fy[i];
  if(vis[nx][ny]==0&&map[nx][ny]==0&&nx>=0&&nx<5&&ny>=0&&ny<5)
  { vis[nx][ny]=1;
   q[last].x=nx;
   q[last].y=ny;
   q[last].pre=front;
   last++;
  }
  if(nx==4&&ny==4)
  { print(last-1);//我的last最后多加了一次,所以减了一
   break;
  }
 }
 front++;
 } 
 return 0;
}

3.红与黑

https://vjudge.net/problem/OpenJ_Bailian-2816

  用广域搜索,应为要找最多走好多块砖,所以我们对下一个点的限制就改为只要在图内就可以了。

 

#include<stdio.h>
#include<string.h>
#define N 25
int w,h,cnt;
char map[N][N];
bool vis[N][N];
int fx[4]={0,1,-1,0};
int fy[4]={1,0,0,-1};
void bfs(int x,int y)
{    int i,nx,ny;
    for(i=0;i<4;i++)
    {    nx=x+fx[i];
        ny=y+fy[i];
        if(map[nx][ny]==.&&!vis[nx][ny]&&nx>=0&&nx<h&&ny>=0&&ny<w)//无限走下去,把能走的黑砖都走了
        {    vis[nx][ny]=1;
            cnt++;
            bfs(nx,ny);
        }
    }
}
int main()
{    int i,j,x,y;
    while(~scanf("%d %d",&w,&h))
    {    memset(map,0,sizeof map);
        memset(vis,0,sizeof vis);
        if(w==0&&h==0)
        break;
        else
        {    cnt=1;
        for(i=0;i<h;i++)
        {    getchar();
            for(j=0;j<w;j++)
            {    scanf("%c",&map[i][j]);
                if(map[i][j]==@)
                {    x=i;
                    y=j;
                }
            }
        }
        bfs(x,y);
        printf("%d\n",cnt);
        }
    }
    return 0;
}

 

4.Find a way

https://vjudge.net/problem/HDU-2612

  从两个人的出发点挨到遍历,找到每个人到目的点的最短时间,然后存到一个数组里面,最后把两个存时间的数组的值加起来,比较取最小值。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 205
#define max 0x3f3f3f3f
char map[N][N];
int step1[N][N],step2[N][N];
bool vis[N][N];
struct node
{ int x,y;
};
queue<node>q;
int n,m,x1,x2,y1,y2;
int fx[4]={0,1,-1,0};
int fy[4]={1,0,0,-1};
void bfs(int x,int y,int step[][205])
{ int i;
 node now,next;
 vis[x][y]=1;
 step[x][y]=0;
 q.push({x,y});
 while(!q.empty())
 { now=q.front();
  q.pop();
  for(i=0;i<4;i++)
  { next.x=now.x+fx[i];
   next.y=now.y+fy[i];
   if(!vis[next.x][next.y]&&(map[next.x][next.y]==‘.‘||map[next.x][next.y]==‘@‘)&&next.x>=0&&next.x<n&&next.y>=0&&next.y<m)//注意下一个能走的点的条件是!‘#‘。
   { step[next.x][next.y]=step[now.x][now.y]+1;
    vis[next.x][next.y]=1;
    q.push(next);
   }
  }
 }
}
int main()
{ int i,j,maxx;
 while(scanf("%d %d",&n,&m)!=EOF)
 { maxx=max;
  memset(map,0,sizeof map);
  memset(step1,0,sizeof step1);
  memset(step2,0,sizeof step2);
  memset(vis,0,sizeof vis);
  for(i=0;i<n;i++)
  { scanf("%s",&map[i]);
   for(j=0;j<m;j++)
   { if(map[i][j]==‘Y‘)
    x1=i,y1=j;
    if(map[i][j]==‘M‘)
    x2=i,y2=j;
   }
  }
  bfs(x1,y1,step1);
  memset(vis,0,sizeof vis);
  bfs(x2,y2,step2);
  for(i=0;i<n;i++)
  { for(j=0;j<n;j++)
   { if(map[i][j]==‘@‘&&maxx>step1[i][j]+step2[i][j]&&step1[i][j]!=0&&step2[i][j]!=0)
    { maxx=step1[i][j]+step2[i][j];
    }
   }
  }
  printf("%d\n",maxx*11);
 }
}

 

 

5.Catch That Cow

https://vjudge.net/problem/POJ-3278

这个题要注意就是农民的位置比牛前面时我们只有一步一步的倒退了,要分情况,牛在农夫前的情况:还是遍历每个点,但是跟之前的不一样,他不在单纯的加减了,他还要翻倍,我们在循环时对循环次数分情况来弄就可以了。

 

#include<stdio.h>
#include<string.h>
#include<queue>
#define N 100005
using namespace std;
bool vis[N];
int step[N];
int bfs(int n,int k)
{ int now,next,i;
 queue<int>q;
 q.push(n);
 vis[n]=1;
 while(!q.empty())
 { now=q.front();
  q.pop();
  for(i=0;i<3;i++)
  { if(i==0)
   next=now+1;
   else if(i==1)
   next=now-1;
   else if(i==2)
   next=now*2;
   if(next>=0&&next<=100000&&!vis[next])
   { step[next]=step[now]+1;
    vis[next]=1;
    q.push(next);
   }
   if(next==k)
   return step[next];
  }
 }
}
int main()
{ int n,k,i,sum=0;
 while(~scanf("%d %d",&n,&k))
 { if(n>=k)
 printf("%d\n",n-k);
 else
 { memset(step,0,sizeof step);
  memset(vis,0,sizeof vis);
  sum=bfs(n,k);
  printf("%d\n",sum);
 }
 }
 return 0;
}

搜索题解

标签:nod   std   sizeof   getc   turn   mes   bre   个人   i++   

原文地址:https://www.cnblogs.com/J-J-J/p/12230213.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!