[hihoCoder太閣最新面經算法競賽1] 穿越禁區 (DFS,並查集,計算幾何) 難題

描述

作爲H國的精英特工,你接到了一項任務,駕駛一輛吉普穿越佈滿監測雷達的禁區。爲了簡化題目,我們可以把禁區想象爲一個左下角是(0, 0)右上角是( WH )的長方形區域。區域中一共有 N 座雷達,其中第 i 座的座標是(Xi,Yi ),監測範圍是半徑爲 Ri 的圓形區域。所有在圓內和圓上的運載工具都會被監測到。

你的目標是從左到右穿越禁區。你可以選擇線段(0, 0)-(0, H)上任意一點作爲起點,線段(W, 0)-(WH)上任意一點作爲終點。在禁區內你可以沿任意路線行駛,只要保持始終在禁區內並且沒有被雷達監測到。

給出禁區內的雷達部署方案,你需要判斷是否存在滿足條件的行駛路線。

輸入

輸入包含多組數據。

第1行是一個整數 T,表示以下有 T 組數據 (1 ≤ T ≤ 10)。

每組數據的第1行:三個整數 WHN (0 ≤ WH ≤ 1000000, 1 ≤ N ≤ 1000)。

每組數據的第2-N+1行:每行三個整數XiYiRi (0 ≤ Xi ≤ W, 0 ≤ Yi ≤ H, 1 ≤ Ri ≤ 1000000)。

輸出

對於每組數據輸出"YES"或者"NO"表示是否有滿足條件的行駛路線。

樣例輸入
2
10 4 2
5 1 1
5 3 1
10 4 2
5 1 1
6 3 1
樣例輸出
NO
YES

題解: 橫向考察,每一條水平線方向,都不能有相交的若干圓覆蓋[0,H]。這樣才能通過。

方法一: DFS
#include <stdio.h>

int graph[1024][1024];
int x[1024], y[1024], r[1024];

void build_graph(int N) {
	int nein[1024] = {0};
	for (int i = 0; i < N; ++i) {
		for (int j = i + 1; j < N; ++j) {
			long long dx = x[i] - x[j], dy = y[i] - y[j], sr = r[i] + r[j];
			if (dx * dx + dy * dy <= sr * sr) {
				graph[i][nein[i]] = j;
				graph[j][nein[j]] = i;
				nein[i]++;
				nein[j]++;
			}
		}
	}
	for (int i = 0; i < N; ++i)
		graph[i][nein[i]] = -1;
}

int dfs(int i, int* done) {
	done[i] = 1;
	if (y[i] - r[i] <= 0)
		return 1;
	for (int k = 0; graph[i][k] != -1; ++k) {
		int j = graph[i][k];
		if (done[j] == 0)
			if (dfs(j, done))
				return 1;
	}
	return 0;
}

int main() {
	int T, W, H, N;
	scanf("%d", &T);
	for (int t = 0; t < T; ++t) {
		scanf("%d%d%d", &W, &H, &N);
		for (int i = 0; i < N; ++i)
			scanf("%d%d%d", &(x[i]), &(y[i]), &(r[i]));
		build_graph(N);
		int done[1024] = {};
		int find = 0;
		for (int i = 0; i < N; ++i) {
			if (y[i] + r[i] >= H) {
				if (dfs(i, done)) {
					find = 1;
					printf("NO\n");
					break;
				}
			}
		}
		if (find == 0)
			printf("YES\n");
	}
}

方法二: 並查集

#include<iostream>
#include<vector>
#include<algorithm>
#include<limits.h>
#include<set>
#include<math.h>
using namespace std;

int main()
{
    vector<pair<int ,int> > vec;
    int T, W, H, N, xi, yi, ri;
    cin >> T;
    while(T--)
    {
        cin >> W >> H >> N;
        vector<vector<int> > radars;
        for(int i = 0; i < N; i++)
        {
            cin >> xi >> yi >> ri;
            radars.push_back(vector<int>{xi, yi, ri});
        }
        int ans = 1;
        vector<int> hash(N);
        for(int i = 0; i < N ;i++) hash[i] = i; 
        for(int i =0; i< N; i++)
        {
            int x1 = radars[i][0], y1 = radars[i][1], r1 = radars[i][2];
            for(int j = i+1; j < N; j++)
            {
                int x2 = radars[j][0], y2 = radars[j][1], r2 = radars[j][2];
                float dis = sqrt(pow(x1-x2, 2)+ pow(y1-y2, 2));
                if(dis <= r1+r2)
                {
                    int par1 = hash[j], par2 = hash[i];
                    while(hash[par1] != par1) par1 = hash[par1]; 
                    while(hash[par2] != par2) par2 = hash[par2];
                    hash[par1] = par2;
                }
            }
        } 
        set<int> parent;
        for(int i =0; i< N; i++)
        {
            int par = hash[i];
            while(par != hash[par]) par = hash[par];
            hash[i] = par;
            parent.insert(par);
        }

        for(int val: parent)
        {
            int top = INT_MIN, bot = INT_MAX;
            for(int i = 0; i < N; i++)
            {
                if(hash[i] == val)
                {
                    top = max(top, radars[i][1] + radars[i][2]); 
                    bot = min(bot, radars[i][1] - radars[i][2]);
                    if(top >= H && bot <=0)
                    {
                        ans = 0;
                        i = N;
                        break;
                    }
                }    
            }
            if(ans == 0) break;
        }

        if(ans) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;
}


發佈了81 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章