算法競(jìng)賽2022年第十三屆藍(lán)橋杯C++ B組_掃雷
#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]; // 判斷是否訪(fǎng)問(wèn)過(guò)
typedef long long ll;
ll h[M]; // 哈希數(shù)組
int id[M], res; // id數(shù)組為哈希數(shù)組中key對(duì)應(yīng)的地雷原來(lái)下標(biāo)
ll get_hs(int x, int y) { // 得到每個(gè)坐標(biāo)的哈希值
? ? return (ll)x * X + y;
}
int find(int x, int y) { // 找到該坐標(biāo)被哈希數(shù)組存儲(chǔ)的下標(biāo)key
? ? ll hs = get_hs(x, y);
? ? int key = (hs % M + M) % M; // 映射到哈希數(shù)組內(nèi)部
? ? // 如果該位置已經(jīng)被占用并且不等于我們要求的哈希值,要在之后找到相應(yīng)位置
? ? while(h[key] != -1 && h[key] != hs) {?
? ? ? ? key++;
? ? ? ? if(key == M) key = 0; // 哈希表走到末尾,又從0開(kāi)始
? ? }
? ? 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); // 找到該坐標(biāo)點(diǎn)對(duì)應(yīng)的哈希下標(biāo)
? ? ? ? ? ? ?
? ? ? ? ? ? ? ? // 如果該點(diǎn)有地雷,沒(méi)有被訪(fǎng)問(wèn)過(guò),能被炸到
? ? ? ? ? ? ? ? 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);// 找到該坐標(biāo)點(diǎn)對(duì)應(yīng)的哈希下標(biāo)
? ? ? ? if(h[key] == -1) h[key] = get_hs(x, y); // 如果哈希對(duì)應(yīng)位置為空,則插入
? ? ? ? // id數(shù)組沒(méi)有被標(biāo)記或者找到了同一個(gè)坐標(biāo)點(diǎn)更大半徑的地雷
? ? ? ? if(!id[key] || b[id[key]].r < r) {?
? ? ? ? ? ? id[key] = i;
? ? ? ? }
? ? }
? ? for(int i = 1; i <= m; i++) { // 枚舉導(dǎo)彈
? ? ? ? //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);
? ? ? ? ? ? ? ? // 如果該點(diǎn)有地雷,沒(méi)有被訪(fǎng)問(wèn)過(guò),能被炸到
? ? ? ? ? ? ? ? if(id[key] && !st[id[key]] && check(x, y, r, xx, yy)) dfs(id[key]);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? // 遍歷每個(gè)地雷,看是否被標(biāo)記
? ? for(int i = 1; i <= n; i++) {
? ? ? ? int key = find(b[i].x, b[i].y); // 獲得坐標(biāo)點(diǎn)對(duì)應(yīng)哈希下標(biāo)
? ? ? ? int pos = id[key]; // 哈希下標(biāo)對(duì)應(yīng)的地雷原來(lái)下標(biāo),可能與i不同
? ? ? ? if( st[pos]) res++; // 如果有地雷并且被訪(fǎng)問(wèn)過(guò)
? ? }
? ? cout << res<<endl;
? ? return 0;
}