【B题】
抓住奶牛,已知起点求到终点的最少步数,那就是BFS。
只有三种方向:x+1,x-1,x*2.
数的范围是[0,100000];
那么就去用BFS遍历这100000个数;
如果第一次走到了终点,那么这个步数就是最少的步数.
代码如下:
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int dir[4][2]={-1,0,0,-1,1,0,0,1};
int use[30][30]; //标记是否走过这个点
char mp[30][30]; //存图
int n,m;
struct node //结构体存点坐标(x,y)
{
int x;
int y;
};
int bfs(int sx,int sy)
{
int cnt=1; //开一个cn 计数
queue<node> qu;
memset(use,0,sizeof(use)); // 初始化标记数组,表示图上面的每个点都没有走过
node now,next;
now.x=sx;
now.y=sy;
use[sx][sy]=1;
qu.push(now); //起点入队列
while(!qu.empty()) //判空
{
now=qu.front(); //取一个点
qu.pop();
for(int i=0;i<4;i++) //遍历上下左右四个点
{
int dx=now.x+dir[i][0];
int dy=now.y+dir[i][1];
if(mp[dx][dy]=='.'&&use[dx][dy]==0&&dx>=0&&dx<n&&dy>=0&&dy<m) //是否重复走过,并且是能走的点
{
use[dx][dy]=1; //标记走过
cnt++; //计数+1
next.x=dx;
next.y=dy;
qu.push(next); //现在的点入队列 搜下一个点
}
}
}
return cnt;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
if(n==0&&m==0)
break;
for(int i=0;i<n;i++)
scanf("%s",mp[i]);
int x,y;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mp[i][j]=='@') //找起点
{
x=i;
y=j;
}
}
}
int ans=bfs(x,y);
printf("%d\n",ans);
}
return 0;
}
【C题】
有n层电梯,每个电梯可以走的【i+k[i]】层,求出从起点走到终点的最少步数。
也是BFS,以步数分成,求出走一步,走两步.........能够走到的地方。
数据范围是[1,200];
那么就遍历这200个点,求出从起点到每个点的最少步数。
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int n,a,b;
int k[300];
int use[300];
struct node
{
int x; //走到点的坐标
int step; //走到那个点需要的最短步数
};
int check(int x) //判断边界 比如走到201 那么就肯定是不可能的
{
if(x>=1&&x<=n)
return 1;
return 0;
}
int bfs()
{
queue<node>qu;
memset(use,0,sizeof(use)); //标记第一次走到
node now,next;
now.x=a;
now.step=0;
use[a]=1;
qu.push(now); //起点入队列
while(!qu.empty())
{
now=qu.front();
qu.pop();
if(now.x==b) //如果走到了这个点,就直接返回步数就行了
return now.step;
int dx;
dx=now.x+k[now.x]; //按照第一种方式走
if(check(dx)==1&&use[dx]==0) //如果没有走过并且满足边界
{
use[dx]=1;
next.x=dx;
next.step=now.step+1;
qu.push(next);
}
dx=now.x-k[now.x]; //按照第二种方式走
if(check(dx)==1&&use[dx]==0)
{
use[dx]=1;
next.x=dx;
next.step=now.step+1;
qu.push(next);
}
}
return -1; //如果所有的遍历都走不到终点,就输出-1
}
int main()
{
while(scanf("%d",&n),n)
{
scanf("%d%d",&a,&b);
for(int i=1;i<=n;i++)
scanf("%d",&k[i]);
int ans=bfs();
printf("%d\n",ans);
}
return 0;
}
【D题】
按照象棋中马的走法,求出从起点走到终点的最少步数。
也是BFS,但是跟前面的题不一样在于,走的方向是不同的,不是按照上下左右的方向来走,而是象棋马的走法,大家推一下就可以知道方向数组该怎么写了。
标记数组,标记走到这个点第一次走到。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
char map[10][10];
int dir[8][2]={1,2,1,-2,-1,-2,-1,2,2,1,2,-1,-2,1,-2,-1}; //方向数组,8个方向
int use[10][10];
int s,e,ss,ee;
struct node //点坐标和走到这个点的最少步数
{
int x;
int y;
int step;
};
int BFS()
{
queue<node>que;
node now,next; //处理起点
now.x=s;
now.y=e;
now.step=0;
use[s][e]=1;
que.push(now);
while(!que.empty())
{
now=que.front();
que.pop();
if(now.x==ss&&now.y==ee) //是否走到终点
return now.step;
for(int i=0;i<8;i++) //8个方向走
{
int dx=now.x+dir[i][0];
int dy=now.y+dir[i][1];
if(dx>=1&&dx<=8&&dy>=1&&dy<=8&&use[dx][dy]==0) //第一次走到且在边界里面
{
use[dx][dy]=1;
next.x=dx;
next.y=dy;
next.step=now.step+1;
que.push(next);
}
}
}
}
int main()
{
char s1[5],s2[5];
while(scanf("%s%s",s1,s2)!=EOF)
{
memset(use,0,sizeof(use)); //初始化标记数组
s=s1[0]-'a'+1;
e=s1[1]-'0';
ss=s2[0]-'a'+1;
ee=s2[1]-'0';
int ans=BFS();
printf("To get from %s to %s takes %d knight moves.\n",s1,s2,ans);
}
return 0;
}
【E题】
给出起点和终点,判断是否在时间限制以内从起点走到终点。
也是BFS遍历从起点到终点,但是难点在于这个是两层图,可以在第一层和第二层之间来回走动,认真独题,按照规定来走就行了;
#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;
char mp[2][15][15]; //存图,因为是两层图,所以是三维数组,mp[0][][]代表第一层的图,mp[1][][]代表第二层的图
int use[2][15][15]; //标记是否是第一次走的标记数组 跟存图一样是三维的
int n,m,t,flag;
int dir[4][2]={-1,0,0,-1,1,0,0,1}; //方向
struct node
{
int z; //该点的坐标,位于第z层中的(x,y),走到这里花的最短时间是time.
int x;
int y;
int time;
}ans;
queue<node> que;
void BFS()
{
while(!que.empty())
{
node tem=que.front();
que.pop();
if(mp[tem.z][tem.x][tem.y]=='P')
{
if(tem.time<=t)
{
flag=1;
return ;
}
}
node next;
for(int i=0;i<4;i++) //四个方向
{
next.z=tem.z;
next.x=tem.x+dir[i][0];
next.y=tem.y+dir[i][1];
next.time=tem.time+1;
if(next.z==1&&!use[next.z][next.x][next.y]&&next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&mp[next.z][next.x][next.y]=='#'&&next.time<=t)
{
if(mp[0][next.x][next.y]!='#'&&mp[0][next.x][next.y]!='*')
{
use[next.z][next.x][next.y]=1;
next.z=0;
que.push(next);
}
}
if(next.z==0&&!use[next.z][next.x][next.y]&&next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&mp[next.z][next.x][next.y]=='#'&&next.time<=t)
{
if(mp[1][next.x][next.y]!='#'&&mp[1][next.x][next.y]!='*')
{
use[next.z][next.x][next.y]=1;
next.z=1;
que.push(next);
}
}
if(mp[next.z][next.x][next.y]!='#'&&!use[next.z][next.x][next.y]&&next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&mp[next.z][next.x][next.y]!='*'&&next.time<=t)
{
use[next.z][next.x][next.y]=1;
que.push(next);
}
}
}
}
int main()
{
int i,j,k,T;
scanf("%d",&T);
while(T--)
{
flag=0;
while (!que.empty())
que.pop();
memset(use,0,sizeof(use));
scanf("%d%d%d",&n,&m,&t);
for(i=0;i<2;i++)
for(j=0;j<n;j++)
scanf("%s",mp[i][j]);
ans.x = 0, ans.y = 0, ans.z = 0, ans.time = 0;
use[0][0][0]=1;
que.push(ans);
BFS();
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}