[2015编程之美] 资格赛C

#1150 : 基站选址

时间限制:2000ms
单点时限:1000ms
内存限制:256MB

描述

需要在一个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

模拟退火,死活过不了,贴一个Wa代码,望路过大神指正
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cstdlib>
using namespace std;
#define ll long long
#define INF 1e40
#define PI acos(-1.0)
#define N 1010

struct Point
{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
};
int n,m;
double lx,ly;
Point p[N],q[N];
int dir[9][2]={0,1,0,-1,1,0,-1,0,-1,-1,1,1,-1,1,1,-1,0,0};

double cal(Point t)
{
    double sum=INF;
    for(int i=1;i<=m;i++) sum=min(sum,fabs(q[i].x-t.x)+fabs(q[i].y-t.y));
    for(int i=1;i<=n;i++) sum+=(p[i].x-t.x)*(p[i].x-t.x)+(p[i].y-t.y)*(p[i].y-t.y);
    return sum;
}
void solve()
{
    int TN=4,DN=50;
    Point u,v,ansp;
    double ud,vd,ansd=INF;
    double step=sqrt(lx*lx+ly*ly),eps=1e-4,r=0.95;

    while(TN--)
    {
        u=Point(rand()%int(lx),rand()%int(ly));
        ud=cal(u);
        ud=cal(u);
        while(step>eps)
        {
            bool flag=1;
            while(flag)
            {
                flag=0;
                for(int i=0;i<DN;i++)
                {
                    double d=2*PI*(double)rand()/RAND_MAX;
                    v.x=u.x+sin(d)*step;
                    v.y=u.y+cos(d)*step;
                    if(v.x<0 || v.x>lx || v.y<0 || v.y>ly) continue;
                    vd=cal(v);
                    if(vd<ud) ud=vd,u=v,flag=1;
                }
            }
            step*=r;
        }
        if(ud<ansd) ansd=ud,ansp=u;
    }
    double ans=INF;
    for(int i=0;i<9;i++)
    {
        int x=(int)ansp.x+dir[i][0];
        int y=(int)ansp.y+dir[i][1];
        if(x<0 || x>lx || y<0 || y>ly) continue;
        double tt=cal(Point(x,y));
        ans=min(ans,tt);
    }
    printf("%.0f\n",ans);
}
int main()
{
    int T,iCase=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf%lf%d%d",&lx,&ly,&n,&m);
        for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
        for(int i=1;i<=m;i++) scanf("%lf%lf",&q[i].x,&q[i].y);
        printf("Case #%d: ",iCase++);
        solve();
    }
    return 0;
}
posted @ 2015-05-02 23:17  哈特13  阅读(234)  评论(0编辑  收藏  举报