【编程之美】题目3:基站选址
source:http://hihocoder.com/contest/msbop2015qual/problem/3
描述
需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上。
网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方。
网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离)。
在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价。
输入
第一行为一个整数T,表示数据组数。
每组数据第一行为四个整数:N, M, A, B。
接下来的A+B行每行两个整数x, y,代表一个坐标,前A行表示各用户的坐标,后B行表示各通讯公司的坐标。
输出
对于每组数据输出一行"Case #X: Y",X代表数据编号(从1开始),Y代表所求最小代价。
数据范围
1 ≤ T ≤ 20
1 ≤ x ≤ N
1 ≤ y ≤ M
1 ≤ B ≤ 100
小数据
1 ≤ N, M ≤ 100
1 ≤ A ≤ 100
大数据
1 ≤ N, M ≤ 107
1 ≤ A ≤ 1000
样例输入
2 3 3 4 1 1 2 2 1 2 3 3 2 2 2 4 4 4 2 1 2 2 4 3 1 4 3 1 4 1 3
样例输出
Case #1: 4 Case #2: 13
解体思路:类似于建邮局问题,转换为平均数。
#include <iostream> #include <vector> #include <algorithm> #include <climits> //#include <fstream> using namespace std; const int XX[4]={0,0,1,1}; const int YY[4]={0,1,0,1}; int main(){ //ifstream cin("2.txt"); int T; cin >> T; for(int icase = 1; icase <= T; ++ icase){ long long N,M,A,B; cin >>N>>M>>A>>B; vector<long long> a_x(A,0), a_y(A,0); vector<long long> b_x(B,0), b_y(B,0); for(int i = 0 ; i < A; ++ i ) cin >> a_x[i]>>a_y[i]; for(int i = 0 ; i < B; ++ i) cin >> b_x[i] >> b_y[i]; long long sum_a_x_2 = 0, sum_a_x = 0, sum_a_y = 0, sum_a_y_2 = 0; for(int i = 0 ; i < A ; ++ i){ sum_a_x_2+=a_x[i]*a_x[i]; sum_a_x +=a_x[i]; sum_a_y +=a_y[i]; sum_a_y_2+=a_y[i]*a_y[i]; } long long x = sum_a_x/A, y=sum_a_y/A, ans = LLONG_MAX; for(int i = 0 ; i < 4; ++ i){ long long curx = x + XX[i], cury = y+YY[i],total_dis = LLONG_MAX; long long curResult = sum_a_x_2 + A*curx*curx-2*curx*sum_a_x + sum_a_y_2 + A*cury*cury - 2*cury*sum_a_y; for(int j = 0 ; j < B; ++ j){ total_dis = min(total_dis,abs(curx-b_x[j])+abs(cury-b_y[j])); } ans = min(ans,curResult+total_dis); } cout<<"Case #"<<icase<<": "<<ans<<endl; } }