NEUQ-ACM预备队必做题-6

P1135 奇怪的电梯

使用bfs,从第a楼出发遍历所有经过的楼层,先将第a楼放置于队列中,当队列非空时取出队头元素,如果队头元素在1~楼高的范围内,且未被设flag,则认定该元素符合要求,设flag并放入队列,直至访问到第b楼,用一个node结构体记录每层楼到达时所按下的按钮次数。

#include <iostream>
#include <queue>
using namespace std;

struct node{
    int floor;
    int counts;
};

int main() {
    int n, a, b, nums[1000],flags[1000] = {0};
    cin >> n >> a >> b;
    for (int i = 1; i <= n; i++) {
        cin >> nums[i];
    }
    queue<node> q;
    node p={a,0};
    q.push(p);
    flags[a]=1;
    node cur;
    while(!q.empty()){
        cur = q.front();
        q.pop();
        if(cur.floor==b){break;}
        int temp = cur.floor+nums[cur.floor];
        if(temp<=n&&flags[temp]==0){
            p = {temp,cur.counts+1};
            q.push(p);
            flags[temp]=1;
        }
        temp = cur.floor-nums[cur.floor];
        if(temp>=1&&flags[temp]==0){
            p={temp,cur.counts+1};
            q.push(p);
            flags[temp]=1;
        }
    }
    if(cur.floor==b){
        cout << cur.counts;
    }else{
        cout << -1;
    }
    return 0;


}

P1443 马的遍历

使用bfs,遍历过程为马走日的八个方向,思路同上一题。

#include <iostream>
#include <queue>
using namespace std;

struct node{
    int x,y,count;
};

int main() {
    int m,n,x,y,flags[410][410]={0},counts[410][410];
    queue<node> q;
    cin>>n>>m>>x>>y;
    node p={x,y,0};
    flags[x][y]=1;
    counts[x][y]=0;
    q.push(p);
    while(!q.empty()){
        node cur = q.front();
        q.pop();
        if(cur.x+2<=n&&cur.y+1<=m&&flags[cur.x+2][cur.y+1]==0){
            p={cur.x+2,cur.y+1,cur.count+1};
            q.push(p);
            flags[cur.x+2][cur.y+1]=1;
            counts[cur.x+2][cur.y+1]=cur.count+1;
        }
        if(cur.x+1<=n&&cur.y+2<=m&&flags[cur.x+1][cur.y+2]==0){
            p={cur.x+1,cur.y+2,cur.count+1};
            q.push(p);
            flags[cur.x+1][cur.y+2]=1;
            counts[cur.x+1][cur.y+2]=cur.count+1;
        }
        if(cur.x-2>=1&&cur.y+1<=m&&flags[cur.x-2][cur.y+1]==0){
            p={cur.x-2,cur.y+1,cur.count+1};
            q.push(p);
            flags[cur.x-2][cur.y+1]=1;
            counts[cur.x-2][cur.y+1]=cur.count+1;
        }
        if(cur.x-1>=1&&cur.y+2<=m&&flags[cur.x-1][cur.y+2]==0){
            p={cur.x-1,cur.y+2,cur.count+1};
            q.push(p);
            flags[cur.x-1][cur.y+2]=1;
            counts[cur.x-1][cur.y+2]=cur.count+1;
        }

        if(cur.x+2<=n&&cur.y-1>=1&&flags[cur.x+2][cur.y-1]==0){
            p={cur.x+2,cur.y-1,cur.count+1};
            q.push(p);
            flags[cur.x+2][cur.y-1]=1;
            counts[cur.x+2][cur.y-1]=cur.count+1;
        }
        if(cur.x+1<=n&&cur.y-2>=1&&flags[cur.x+1][cur.y-2]==0){
            p={cur.x+1,cur.y-2,cur.count+1};
            q.push(p);
            flags[cur.x+1][cur.y-2]=1;
            counts[cur.x+1][cur.y-2]=cur.count+1;
        }
        if(cur.x-2>=1&&cur.y-1>=1&&flags[cur.x-2][cur.y-1]==0){
            p={cur.x-2,cur.y-1,cur.count+1};
            q.push(p);
            flags[cur.x-2][cur.y-1]=1;
            counts[cur.x-2][cur.y-1]=cur.count+1;
        }
        if(cur.x-1>=1&&cur.y-2>=1&&flags[cur.x-1][cur.y-2]==0){
            p={cur.x-1,cur.y-2,cur.count+1};
            q.push(p);
            flags[cur.x-1][cur.y-2]=1;
            counts[cur.x-1][cur.y-2]=cur.count+1;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(flags[i][j]==1){
                cout << counts[i][j]<<' ';
            }else{
                cout << -1<<' ';
            }

        }
        cout << endl;
    }
}

P3958 [NOIP2017 提高组] 奶酪

使用dfs,在输入的时候判断这个洞是否可以作为起始洞,将其推入起始洞队列,以第一个起始洞为起点dfs遍历所有洞口,当遍历过程中能够出奶酪则判断为Yes,当遍历结束后再次取出一个起始洞进行遍历,直至所有的起始洞都被访问未知,可认定为No。

#include <iostream>
#include <math.h>
#include <queue>
using namespace std;

struct node{
    double index;
    double x,y,z;
};

double calDistance(node p1,node p2){
    return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)+(p2.z-p1.z)*(p2.z-p1.z));
}

int main() {
    int T;
    cin >> T;
    for(int k=0;k<T;k++){
        long long n;
        node points[1010];
        int flags[1010]={0};
        queue<node> q;
        long long h,r;
        cin >> n>>h>>r;
        queue<node> startP;
        for(long long i=1;i<=n;i++){
            cin >> points[i].x>>points[i].y>>points[i].z;
            if(points[i].z-r<=0){
                startP.push(points[i]);
                flags[i]=1;
            }
            points[i].index=i;
        }
        if(startP.empty()){
            cout << "No"<<endl;
            continue;
        }
        node p = startP.front();
        startP.pop();
        q.push(p);
        while(!q.empty()){
            node cur = q.front();
            q.pop();
            if(cur.z+r>=h){
                cout << "Yes"<<endl;
                break;
            }
            for(long long i=1;i<=n;i++){
                if(flags[i]==1){ continue;}
                if(calDistance(cur,points[i])<=2*r){
                    q.push(points[i]);
                    flags[i]=1;
                }
            }
            if(q.empty()&&!startP.empty()){
                p=startP.front();
                startP.pop();
                q.push(p);
            }else if(q.empty()&&startP.empty()){
                cout << "No"<<endl;
                break;
            }
        }
    }
}

P1162 填涂颜色

先去找被围住的一个点,然后从这个点出发水漫整个区域即可,被围住的点的特征为,其上下左右方向至少有一个1作为围墙,水漫过程可以通过队列进行dfs遍历完成。

#include <iostream>
#include <queue>
using namespace std;

struct node{
    int i,j;
};

int main() {
    int n,flag=0,keyI,keyJ;
    int map[35][35];
    cin >> n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin >> map[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(map[i][j]==1){ continue;}

            for(int k=j-1;k>=1;k--){
                if(map[i][k]==1){
                    flag++;
                    break;
                }
            }

            for(int k=j+1;k<=n;k++){
                if(map[i][k]==1){
                    flag++;
                    break;
                }
            }

            for(int k=i-1;k>=1;k--){
                if(map[k][j]==1){
                    flag++;
                    break;
                }
            }

            for(int k=i+1;k<=n;k++){
                if(map[k][j]==1){
                    flag++;
                    break;
                }
            }

            if(flag==4){
                keyI=i;
                keyJ=j;
            }
            flag=0;
        }
    }

    queue<node> q;
    node p={keyI,keyJ};
    map[keyI][keyJ]=2;
    q.push(p);
    while (!q.empty()){
        node cur = q.front();
        q.pop();
        if(map[cur.i+1][cur.j]==0){
            map[cur.i+1][cur.j]=2;
            p={cur.i+1,cur.j};
            q.push(p);
        }
        if(map[cur.i][cur.j+1]==0){
            map[cur.i][cur.j+1]=2;
            p={cur.i,cur.j+1};
            q.push(p);
        }
        if(map[cur.i-1][cur.j]==0){
            map[cur.i-1][cur.j]=2;
            p={cur.i-1,cur.j};
            q.push(p);
        }
        if(map[cur.i][cur.j-1]==0){
            map[cur.i][cur.j-1]=2;
            p={cur.i,cur.j-1};
            q.push(p);
        }
    }

    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<  map[i][j]<<' ';
        }
        cout << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值