CCF計算機職業資格認證考試題解系列文章為meelo原創,請務必以鏈接形式注明本文地址
CCF CSP 201403-4 無線網絡
問題描述
目前在一個很大的平面房間里有 n 個無線路由器,每個無線路由器都固定在某個點上。任何兩個無線路由器只要距離不超過 r 就能互相建立網絡連接。
除此以外,另有 m 個可以擺放無線路由器的位置。你可以在這些位置中選擇至多 k 個增設新的路由器。
你的目標是使得第 1 個路由器和第 2 個路由器之間的網絡連接經過盡量少的中轉路由器。請問在最優方案下中轉路由器的最少個數是多少?
除此以外,另有 m 個可以擺放無線路由器的位置。你可以在這些位置中選擇至多 k 個增設新的路由器。
你的目標是使得第 1 個路由器和第 2 個路由器之間的網絡連接經過盡量少的中轉路由器。請問在最優方案下中轉路由器的最少個數是多少?
輸入格式
第一行包含四個正整數 n,m,k,r。(2 ≤ n ≤ 100,1 ≤ k ≤ m ≤ 100, 1 ≤ r ≤ 10
8)。
接下來 n 行,每行包含兩個整數 x i 和 y i,表示一個已經放置好的無線 路由器在 (x i, y i) 點處。輸入數據保證第 1 和第 2 個路由器在僅有這 n 個路由器的情況下已經可以互相連接(經過一系列的中轉路由器)。
接下來 m 行,每行包含兩個整數 x i 和 y i,表示 (x i, y i) 點處可以增設 一個路由器。
輸入中所有的坐標的絕對值不超過 10 8,保證輸入中的坐標各不相同。
接下來 n 行,每行包含兩個整數 x i 和 y i,表示一個已經放置好的無線 路由器在 (x i, y i) 點處。輸入數據保證第 1 和第 2 個路由器在僅有這 n 個路由器的情況下已經可以互相連接(經過一系列的中轉路由器)。
接下來 m 行,每行包含兩個整數 x i 和 y i,表示 (x i, y i) 點處可以增設 一個路由器。
輸入中所有的坐標的絕對值不超過 10 8,保證輸入中的坐標各不相同。
輸出格式
輸出只有一個數,即在指定的位置中增設 k 個路由器后,從第 1 個路 由器到第 2 個路由器最少經過的中轉路由器的個數。
樣例輸入
5 3 1 3
0 0
5 5
0 3
0 5
3 5
3 3
4 4
3 0
0 0
5 5
0 3
0 5
3 5
3 3
4 4
3 0
樣例輸出
2
解析
路由器構成了一個圖,如果兩個路由器的距離小於r則存在邊。
求解的是最短路徑。圖所有邊的權重均為1,因此可以用廣度優先搜索解決。
搜索的時候需要記錄路徑上所經過的增設路由器的個數,並確保不會超過k。
使用廣度優先搜索的層次遍歷,可以方便地得到第1個路由器與第2個路由器之間的距離。
代碼
C++
#include <cstdio> #include <cmath> #include <queue> #include <vector> #define MAXN 210 using namespace std; int N, M, K, R; bool graph[MAXN][MAXN]; int pos[MAXN][2]; bool inRange(int a, int b, int R) { return sqrt(pow(pos[a][0]-pos[b][0],2)+pow(pos[a][1]-pos[b][1],2))<=R; } int bfs(int s, int t) { vector<bool> visited(M+N); queue<pair<int,int> > q; q.push(make_pair(s,0)); int len = 1, newLen, level = 1; while(len>0) { newLen = 0; for(int l=0; l<len; l++) { pair<int,int> f = q.front(); if(f.first == t) return level-2; q.pop(); for(int i=0; i<N; i++) { if(graph[f.first][i] && !visited[i]) { q.push(make_pair(i,f.second)); visited[i] = true; newLen++; } } for(int i=N; i<N+M; i++) { if(graph[f.first][i] && !visited[i] && f.second<K) { q.push(make_pair(i,f.second+1)); visited[i] = true; newLen++; } } } len = newLen; level++; } return -1; } int main() { scanf("%d%d%d%d", &N, &M, &K, &R); for(int i=0; i<N+M; i++) { scanf("%d%d", &pos[i][0], &pos[i][1]); } for(int i=0; i<N+M; i++) { for(int j=i+1; j<N+M; j++) { graph[i][j] = graph[j][i] = inRange(i, j, R); } } printf("%d", bfs(0, 1)); }
