藍橋杯歷屆試題 郵局(DFS)
阿新 • • 發佈:2019-01-22
問題描述
C村住著n戶村民,由於交通閉塞,C村的村民只能通過信件與外界交流。為了方便村民們發信,C村打算在C村建設k個郵局,這樣每戶村民可以去離自己家最近的郵局發信。
現在給出了m個備選的郵局,請從中選出k個來,使得村民到自己家最近的郵局的距離和最小。其中兩點之間的距離定義為兩點之間的直線距離。 輸入格式 輸入的第一行包含三個整數n, m, k,分別表示村民的戶數、備選的郵局數和要建的郵局數。
接下來n行,每行兩個整數x, y,依次表示每戶村民家的座標。
接下來m行,每行包含兩個整數x, y,依次表示每個備選郵局的座標。
在輸入中,村民和村民、村民和郵局、郵局和郵局的座標可能相同,但你應把它們看成不同的村民或郵局。 輸出格式 輸出一行,包含k個整數,從小到大依次表示你選擇的備選郵局編號。(備選郵局按輸入順序由1到m編號) 樣例輸入 5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2 樣例輸出 2 4 資料規模和約定
現在給出了m個備選的郵局,請從中選出k個來,使得村民到自己家最近的郵局的距離和最小。其中兩點之間的距離定義為兩點之間的直線距離。 輸入格式 輸入的第一行包含三個整數n, m, k,分別表示村民的戶數、備選的郵局數和要建的郵局數。
接下來n行,每行兩個整數x, y,依次表示每戶村民家的座標。
接下來m行,每行包含兩個整數x, y,依次表示每個備選郵局的座標。
在輸入中,村民和村民、村民和郵局、郵局和郵局的座標可能相同,但你應把它們看成不同的村民或郵局。 輸出格式 輸出一行,包含k個整數,從小到大依次表示你選擇的備選郵局編號。(備選郵局按輸入順序由1到m編號) 樣例輸入 5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2 樣例輸出 2 4 資料規模和約定
對於30%的資料,1<=n<=10,1<=m<=10,1<=k<=5;
對於60%的資料,1<=m<=20;
對於100%的資料,1<=n<=50,1<=m<=25,1<=k<=10。
最後兩組資料超時。
#include<iostream> #include<cstring> #include<cmath> using namespace std; int n, m, k,ans[16],cm[56][2]; float d[51][26],sum = 1e9; void dfs( int choice,int cur, float w[51],int a[16]) { if (choice == k) { float su=0; for (int i = 1;i<=n;i++) su += w[i]; if(sum>su) sum = su, memcpy(ans, a, sizeof(ans)); return; } int i = cur + 1; if (i <= m&&k - choice <= 1 + m - i) { int ok = 0; float t[51]; memcpy(t, w, sizeof(t)); a[choice+1] = i; for (int j = 1;j <= n;j++) if (w[j] > d[j][i]) w[j] = d[j][i],ok=1; if (ok) dfs(choice + 1, i, w, a); dfs(choice, i, t, a); } } int main() { float w[51]; int a[16]; cin >> n >> m >> k; for (int i = 1;i <= n;i++) w[i] = 1e9; for (int i = 1;i <= n;i++) cin >> cm[i][0] >> cm[i][1]; for (int j = 1;j <= m;j++) { int x, y; cin >> x >> y; for (int i = 1;i <= n;i++) d[i][j] = sqrt((x - cm[i][0])*(x - cm[i][0]) + (y - cm[i][1])*(y - cm[i][1])); } dfs(0, 0, w, a); for (int i = 1;i <= k;i++) cout << ans[i] << ' '; return 0; }