Week 6 BFS

1. P1135 奇怪的电梯

好的,BFS(一顿暴搜外加数组优化就ok)。

(1)构建状态:这里用的结构体,分别记录当前楼层和下一楼层,包括它们的层级数                                               和到这层的min步数。

(2)构造二叉树:从当前楼层向上向下移动,如果能到下一层(不超过边界 && 之前没到过这一                                 层),将下一层加入队列。

(3)判断输出:如果当前楼层为目标楼层,输出步数;

                           如果到不了目标楼层,即队列为空,二叉树构造完成也没出现该楼层,输出-1。

(4)数组优化:定义一个数组vis[ ]初始值均为0,如果到达第i层,将vis[ i ] = 1,表示已经到过。

#include <bits/stdc++.h>
using namespace std;

int n,a,b;
int k[210],vis[210];
//int ans = -1;
struct pos
{
    int level;//楼层
    int step;//步数
};

void bfs()
{
    pos cur,next;//定义当前楼层和下一层
    cur.level = a;//初始化
    cur.step = 0;
    queue<pos> qu;
    qu.push(cur);
    vis[a] = 1;

    while(!qu.empty()){
        cur = qu.front();
        qu.pop();

        if(cur.level == b){
            cout<<cur.step<<endl;
            return ;
        }
        //向上
        next.level = cur.level + k[cur.level];
        next.step = cur.step+1;
        if(next.level <= n)
            if(vis[next.level] == 0){
                vis[next.level] = 1;
                qu.push(next);
            }
        //向下
        next.level = cur.level - k[cur.level];
        next.step = cur.step+1;
        if(next.level >= 1)
            if(vis[next.level] == 0){
                vis[next.level] = 1;
                qu.push(next);
            }
    }
    cout<<"-1";
    return ;
}

int main()
{
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++){
        cin>>k[i];
        vis[i] = 0;
    }

    bfs();
    return 0;
}

2.P1443 马的遍历

典例BFS。

用STL中的队列queue辅助构建马移动路线(树):马走日,如果从点(i , j)出发有八个方向可以走即点(i+d[x],j+d[y]),如果移动后没出界 && 之前没来过(i+d[x],j+d[y]),则把(i+d[x],j+d[y])加入队列,标记vis(i+d[x],j+d[y])=1表示来过步数+1,并从队列中弹出点(i , j)。

#include <bits/stdc++.h>
using namespace std;

int n,m,x,y;
int vis[405][405],ans[405][405];
queue<int> qx,qy;//分别记录横纵坐标的变化
int dx[8]={-2,-2,2,2,1,-1,1,-1};
int dy[8]={-1,1,-1,1,2,-2,-2,2};//8个方向

void bfs()
{
    memset(ans,-1,sizeof(ans));
    qx.push(x);
    qy.push(y);
    ans[x][y] = 0;
    vis[x][y] = 1;
    while(!qx.empty()){
        for(int i=0;i<8;i++){
            int tempx = qx.front()+dx[i];
            int tempy = qy.front()+dy[i];
            if(tempx>0 && tempx<=n && tempy>0 && tempy<=m && vis[tempx][tempy]==0){
                vis[tempx][tempy] = 1;
                ans[tempx][tempy] = ans[qx.front()][qy.front()]+1;
                qx.push(tempx);
                qy.push(tempy);
            }
        }
        qx.pop();
        qy.pop();
    }
}

int main()
{
    cin>>n>>m>>x>>y;

    bfs();

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            printf("%-5d",ans[i][j]);//控制
        }
        printf("\n");
    }
    return 0;
}

3.P3958 [NOIP2017 提高组] 奶酪

 原题指路:P3958 [NOIP2017 提高组] 奶酪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P3958

先依据洞的高度进行结构体排序,在从前往后遍历洞的数组,如果能和前面的洞相连(两球心的距离大于等于2r)则加入tree[ ],如果遍历结束最后一个洞能到达奶酪上表面,输出"Yes",反之,输出"No"。 

#include <bits/stdc++.h>
#define ll long long
using namespace std;

struct pos
{
    ll x;
    ll y;
    ll z;
};

bool cmp(pos a,pos b)
{
    if(a.z != b.z) return a.z<b.z;
    if(a.x != b.x) return a.x<b.x;
    return a.y<b.y;
}

pos tree[1010],g[1010];

ll dist(ll x1,ll y1,ll z1,ll x2,ll y2,ll z2)
{
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2);
}

int main()
{
    ll t,n,h,r,s;
    int flag=0;
    cin>>t;
    for(int c=1;c<=t;c++)
	{
		scanf("%lld%lld%lld",&n,&h,&r);
		s=0;
		flag=0;
		memset(tree,0,sizeof(tree));//以上是初始化
		for(int i=1;i<=n;i++)
			scanf("%lld%lld%lld",&g[i].x,&g[i].y,&g[i].z);
		sort(g+1,g+1+n,cmp);//排序
		for(int i=1;i<=n;i++)
		{
			flag=0;
			if(g[i].z-r<=0)//如果与下底面相连就直接存入数组
			{
				s++;
				tree[s].x=g[i].x;
				tree[s].y=g[i].y;
				tree[s].z=g[i].z;
			}
			for(int j=1;j<=s;j++)
				if(dist(g[i].x,g[i].y,g[i].z,tree[j].x,tree[j].y,tree[j].z)<=4*r*r)//判断是否相切或相交
				{
					s++;
					tree[s].x=g[i].x;
					tree[s].y=g[i].y;
					tree[s].z=g[i].z;
					break;
				}
			if(tree[s].z+r>=h)//判断是否与上顶面相连
			{
				flag=1;
				break;
			}
		}
		if(flag)
			printf("Yes\n");
		else
			printf("No\n");
	}
    return 0;
}

4.P1162 填涂颜色

原题指路:P1162 填涂颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1162

本题有很多种解决方法,蒟蒻这里只提其中一种。

核心思想:1.把所有的2赋成0

                  2. 把边界处的2改回0

                  3.把与边界处与0相邻的2改回0

#include <bits/stdc++.h>
using namespace std;

int n;
int a[35][35];
int xx[] = {0,0,-1,1};
int yy[] = {-1,1,0,0};


void bfs()
{
    //把边界处的2改回0
    for(int i=0;i<n;i++){
        if(a[0][i]==2) a[0][i]=0;
        if(a[i][0]==2) a[i][0]=0;
        if(a[n][i]==2) a[n][i]=0;
        if(a[i][n]==2) a[i][n]=0;
    }
    //把与边界处与0相邻的2改回0
    for(int k=1;k<=100;k++){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(a[i][j] != 1){
                    if(a[i][j-1]==0 || a[i][j+1]==0 || a[i-1][j]==0 || a[i+1][j]==0)
                        a[i][j] = 0;
                }
            }
        }
    }

    return ;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            cin>>a[i][j];
            if(a[i][j] == 0)
                a[i][j] = 2;//把所有的0赋成2
        }

    bfs();

    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            cout<<a[i][j];
            if(j!=n-1) cout<<' ';
            else cout<<'\n';
        }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

棠梨下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值