zoukankan      html  css  js  c++  java
  • 编程之美2015 #3 基站选址

    题目:

    时间限制: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

    本题采用全查找会超时。

    我的答案:

    #include <iostream>
    #include <vector>
    using namespace std;
    
    struct POINT{
        int x;
        int y;
    };
    int getEuclideanDistance(int x, int y){
        return x*x + y*y;
    }
    int getManhattanDistance(int x, int y){
        return abs(x) + abs(y);
    }
    int main(void){
        int dataNum;
        cin >> dataNum;
        vector<int> answer;
        for (int i = 0; i < dataNum; i++){
            int xmax, ymax, userNum, companyNum;
            POINT users[1000] = { 0 };
            POINT companies[1000] = { 0 };
            cin >> xmax >> ymax >> userNum >> companyNum;
            int xi = xmax, xj = 0, yi = ymax, yj = 0;
            for (int i = 0; i < userNum; ++i){
                cin >> users[i].x >> users[i].y;
                if (users[i].x>xj)
                    xj = users[i].x;
                if (users[i].x < xi)
                    xi = users[i].x;
                if (users[i].y>yj)
                    yj = users[i].y;
                if (users[i].y < yi)
                    yi = users[i].y;
            }
            for (int i = 0; i < companyNum; ++i){
                cin >> companies[i].x >> companies[i].y;
                if (companies[i].x>xj)
                    xj = companies[i].x;
                if (companies[i].x < xi)
                    xi = companies[i].x;
                if (companies[i].y>yj)
                    yj = companies[i].y;
                if (companies[i].y < yi)
                    yi = companies[i].y;
            }
            int minlen = -1;
            for (int x = xi; x <= xj; ++x){
                for (int y = yi; y <= yj; ++y){
                    int olen = 0;
                    for (int i = 0; i < userNum; ++i)
                        olen += getEuclideanDistance(x - users[i].x, y - users[i].y);
                    int mlen = -1;
                    for (int i = 0; i < companyNum; ++i){
                        if (mlen == -1 || mlen>(abs(x - companies[i].x) + abs(y - companies[i].y))){
                            mlen = getManhattanDistance(x - companies[i].x, y - companies[i].y);
                        }
                    }
                    if (minlen == -1 || minlen>(olen+mlen))
                        minlen = olen + mlen;
                }
            }
            answer.push_back(minlen);
        }
        for (int i = 0; i < dataNum; i++)
            cout << "Case #" << i + 1 << ": " << answer[i] << endl;
        return 0;
    }

    最优答案:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <algorithm>
    using namespace std;
    
    #define mxn 200005
    #define LL long long
    #define MP make_pair
    #define REP(i, a, b) for (int i = a; i <= b; ++i)
    #define FOR(i, a, b) for (int i = a; i < b; ++i)
    
    int dx[] = {0, 0, 0, 1, 1, 1, -1, -1, -1};
    int dy[] = {0, 1, -1, 0, 1, -1, 0, 1, -1};
    
    LL ABS(LL x) {
        return x < 0 ? -x : x;
    }
    
    struct point {
        LL x, y;
        point(){};
        point(LL x, LL y):x(x),y(y){}
        point operator - (const point& b) const {
            return point(x - b.x, y - b.y);
        }
        void input() {
            cin >> x >> y;
        }
        LL dis() {
            return x * x + y * y;
        }
        LL len() {
            return ABS(x) + ABS(y);
        }
    }A[1005], B[105];
    
    LL cal(point o, int a, int b) {
        LL ret = ~0uLL >> 1;
        REP(i, 1, b) ret = min(ret, (o - B[i]).len());
        REP(i, 1, a) ret += (o - A[i]).dis();
        return ret;
    }
    
    int main()
    {
        int t, n, m, a, b, cas = 0;
    
        cin >> t;
        while (t--) {
            cin >> n >> m >> a >> b;
            REP(i, 1, a) A[i].input();
            REP(i, 1, b) B[i].input();
            LL ans = ~0uLL >> 1, x = 0, y = 0;
            REP(i, 1, a) x += A[i].x, y += A[i].y;
            x /= a, y /= a;
            FOR(k, 0, 9) {
                LL tx = x + dx[k], ty = y + dy[k];
                if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
                ans = min(ans, cal(point(tx, ty), a, b));
            }
            cout << "Case #" << ++cas << ": " << ans << endl;
        }
        return 0;
    }

     

    “If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.”
  • 相关阅读:
    边工作边刷题:70天一遍leetcode: day 95
    边工作边刷题:70天一遍leetcode: day 96-2
    边工作边刷题:70天一遍leetcode: day 96-1
    边工作边刷题:70天一遍leetcode: day 96
    边工作边刷题:70天一遍leetcode: day 97-3
    边工作边刷题:70天一遍leetcode: day 97-2
    边工作边刷题:70天一遍leetcode: day 97-1
    边工作边刷题:70天一遍leetcode: day 97
    边工作边刷题:70天一遍leetcode: day 40
    边工作边刷题:70天一遍leetcode: day 41-3
  • 原文地址:https://www.cnblogs.com/Scorpio989/p/4442865.html
Copyright © 2011-2022 走看看