欢迎光临散文网 会员登陆 & 注册

算法竞赛2022年第十三届蓝桥杯C++ B组_扫雷

2022-04-15 17:29 作者:Clayton_Zhou  | 我要投稿

#include <iostream>

#include <cstring>

 

using namespace std;


const int N = 5e4 + 10, M = 5e6 + 7, X = 1e9 + 1;

int n, m;

struct node {

    int x, y, r;

}b[N];

bool st[N]; // 判断是否访问过


typedef long long ll;

ll h[M]; // 哈希数组

int id[M], res; // id数组为哈希数组中key对应的地雷原来下标


ll get_hs(int x, int y) { // 得到每个坐标的哈希值

    return (ll)x * X + y;

}


int find(int x, int y) { // 找到该坐标被哈希数组存储的下标key

    ll hs = get_hs(x, y);

    int key = (hs % M + M) % M; // 映射到哈希数组内部

    // 如果该位置已经被占用并且不等于我们要求的哈希值,要在之后找到相应位置

    while(h[key] != -1 && h[key] != hs) { 


        key++;

        if(key == M) key = 0; // 哈希表走到末尾,又从0开始

    }

    return key;

}


// 判断x1,y1为圆心,半径为r的圆是否包含x,y

bool check(int x1, int y1, int r, int x, int y) { 

    int d = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y);

    return d <= r * r;

}

void dfs(int t) {

        st[t] = 1;

        int x = b[t].x, y = b[t].y, r = b[t].r;

        for(int xx = x - r; xx <= x + r; xx++) { // 从(x-r, y-r)枚举到(x+r, y+r)

            for(int yy = y - r; yy <= y + r; yy++) {

                int key = find(xx, yy); // 找到该坐标点对应的哈希下标

             

                // 如果该点有地雷,没有被访问过,能被炸到

                if(id[key] && !st[id[key]] && check(x, y, r, xx, yy)) dfs(id[key]);

            }

        }    

}



int A[8][3]={

{2, 2, 4},

{4, 4, 1},

{4, 4, 3},

{5, 5, 8},

{3, 3, 5}

};


int B[8][3]={

{0,0,3}};


int main() {


n=5; m=1;

   // cin >> n >> m;

    memset(h, -1, sizeof(h));



    int x, y, r;

    for(int i = 1; i <= n; i++) { // 读入地雷,存入哈希表

      //  cin >> x >> y >> r;

x=A[i-1][0]; y=A[i-1][1]; r=A[i-1][2];

b[i].x=x;b[i].y=y;b[i].r=r;


        //b[i] = {x, y, r};

        int key = find(x, y);// 找到该坐标点对应的哈希下标

        if(h[key] == -1) h[key] = get_hs(x, y); // 如果哈希对应位置为空,则插入


        // id数组没有被标记或者找到了同一个坐标点更大半径的地雷

        if(!id[key] || b[id[key]].r < r) { 

            id[key] = i;

        }

    }

    for(int i = 1; i <= m; i++) { // 枚举导弹

        //cin >> x >> y >> r;

x=B[i-1][0]; y=B[i-1][1]; r=B[i-1][2];


        for(int xx = x - r; xx <= x + r; xx++) {// 从(x-r, y-r)枚举到(x+r, y+r)

            for(int yy = y - r; yy <= y + r; yy++) {

                int key = find(xx, yy);


                // 如果该点有地雷,没有被访问过,能被炸到

                if(id[key] && !st[id[key]] && check(x, y, r, xx, yy)) dfs(id[key]);

            }

        }

    }

    // 遍历每个地雷,看是否被标记

    for(int i = 1; i <= n; i++) {

        int key = find(b[i].x, b[i].y); // 获得坐标点对应哈希下标

        int pos = id[key]; // 哈希下标对应的地雷原来下标,可能与i不同

        if( st[pos]) res++; // 如果有地雷并且被访问过

    }

    cout << res<<endl;

    return 0;

}


算法竞赛2022年第十三届蓝桥杯C++ B组_扫雷的评论 (共 条)

分享到微博请遵守国家法律