题目3 : 基站选址
时间限制:
2000ms
单点时限:
1000ms
内存限制:
256MB
-
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
描述
需要在一个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
x,y可以单独考虑,∑(X-xi)^2+|x-a| 在[1,n]整数范围内最小值,解方程即可
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (10000000+10)
#define MAXA (1000+10)
typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int T;
int n,m,A,B;
ll _x[MAXN],_y[MAXN];
ll a2[MAXN],b2[MAXN];
ll f(ll a,ll b,ll c,ll x){return a*x*x+b*x+c;}
ll calc(int i,ll _x[],ll a2[],ll n)
{
ll a=A,b=0,c=0;
For(i,A) b+=-2*_x[i],c+=_x[i]*_x[i];
b+=1;c-=a2[i];
double x= (double)((double)(-b)/double(2*a));
ll X1=floor(x),X2=ceil(x);
ll ans1 = f(a,b,c,a2[i]);
if (0<=X1&&X1<=n&&X1>a2[i]) ans1=min(ans1,f(a,b,c,X1));
if (0<=X2&&X2<=n&&X2>a2[i]) ans1=min(ans1,f(a,b,c,X2));
if (0>a2[i]) ans1=min(ans1,f(a,b,c,0));
if (n>a2[i]) ans1=min(ans1,f(a,b,c,n));
a=A,b=0,c=0;
For(i,A) b+=-2*_x[i],c+=_x[i]*_x[i];
b-=1;c+=a2[i];
x= (double)((double)(-b)/double(2*a));
X1=floor(x),X2=ceil(x);
if (0<=X1&&X1<=n&&X1<a2[i]) ans1=min(ans1,f(a,b,c,X1));
if (0<=X2&&X2<=n&&X2<a2[i]) ans1=min(ans1,f(a,b,c,X2));
if (0<a2[i]) ans1=min(ans1,f(a,b,c,0));
if (n<a2[i]) ans1=min(ans1,f(a,b,c,n));
return ans1;
/* a=n,b=0,c=0;
For(i,n) b+=-2*_y[i],c+=_y[i]*_y[i];
ll Y= floor((double)(-2*a)/double(b));
return ans;
*/
}
int main()
{
// freopen("base.in","r",stdin);
scanf("%d",&T);
For(kcase,T)
{
scanf("%d%d%d%d",&n,&m,&A,&B);
For(i,A)
{
scanf("%lld%lld",&_x[i],&_y[i]);
}
int ans=-1;
For(i,B)
{
scanf("%lld%lld",&a2[i],&b2[i]);
int p=calc(i,_x,a2,n)+calc(i,_y,b2,m);
if (ans==-1||p<ans) ans=p;
}
printf("Case #%d: %lld\n",kcase,ans);
}
return 0;
}