zoukankan      html  css  js  c++  java
  • 基站选址(编程之美2015资格赛)

    时间限制: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 <limits.h>
    #include <malloc.h>
    
    using namespace std;
    
    enum type{base,user};
    
    typedef struct node
    {
        int posx;
        int posy;
        type kind;
    } node;
    
    int findPostive(int data)
    {
        if(data>=0)
            return data;
        else
            return -data;
    }
    
    int main()
    {
        int num;
        cin>>num;
        int k = 0;
        while(k<num)
        {
            int n,m,a,b;
            cin>>n>>m>>a>>b;
            node *data = new node[a+b];
    
            for(int i = 0;i < a+b; i++)
            {
                cin>>data[i].posx>>data[i].posy;
                if(i<a)
                    data[i].kind = user;
                else
                    data[i].kind = base;
            }
            int min = INT_MAX;
            for(int i = 1;i <= n; i++)
                for(int j = 1;j <= m; j++)
                {
                    int l;
                    int cost = 0;
                    for(l = 0;l < a; l++)
                        cost += ((i-data[l].posy)*(i-data[l].posy)+(j-data[l].posx)*(j-data[l].posx));
    
                    int* dis = new int[b];
    
                    for(l = a;l < a+b; l++)
                    {
                        dis[l-a] = (findPostive(i-data[l].posy)+findPostive(j-data[l].posx));
                    }
    
                    int minvalue = INT_MAX;
                    for(int h = 0; h < b; h++)
                        if(dis[h]<minvalue)
                            minvalue = dis[h];
                    free(dis);
                    cost += minvalue;
                    //cout<<cost<<"  hello "<<endl;
                    if(cost<min)
                    min = cost;
                }
            cout<<"Case #"<<(k+1)<<": "<<min<<endl;
            k++;
            free(data);
    
        }
    }
    

      由于上面算法是在每个格子中尝试查找,因此效率比较低,会出现超时,并且有可能溢出。

    设A个用户的位置,设公司的位置,推出代价函数公式为:

    对于变量x和y求导知

    令导数为零,知

    由于x,y只能取格子中的值,即x,y必须为整数,但是上述公式求出的为浮点数,所以共有4个值可以尝试。

    代码如下:

    #include <iostream>
    #include <vector>
    #include <string>
    #include <vector>
    #include <math.h>
    using namespace std;
    #define modnum 100007
    long long cost=0;
    long long maxll=9223372036854775807;
    long long mincost=maxll;
    long long totalAx=0;
    long long totalAxSquare=0;
    long long totalAy=0;
    long long totalAySquare=0;
    vector<long long> bx;
    vector<long long> by;
    int N,M,A,B;
    long long cal(long long totalSquare,long long total,long long x,long long num) 
    {
        long long ans=0;
        ans+=totalSquare+num*x*x-2*total*x;
        return ans;
    }
    long long calAll(long long x,long long y)           
    {
        long long ans=maxll;
        for(int i=0;i<bx.size();i++)
        {
            ans=min(ans,abs(bx[i]-x)+abs(by[i]-y));      
        }
        return ans+cal(totalAxSquare,totalAx,x,A)+cal(totalAySquare,totalAy,y,A);   
    }
    int main()
    {
        
        int T=0;
        int Case=0;
        cin>>T;
        while(T)
        {
            bx.clear();
            by.clear();
            totalAx=0;
            totalAxSquare=0;
            totalAy=0;
            totalAySquare=0;
            
            T--;
            Case++;
    
            
            cin>>N>>M>>A>>B;
            long long ans=maxll;
            long long temp=0;
            for(int i=0;i<A;i++)      
            {
                cin>>temp;
                totalAx+=temp;
                totalAxSquare+=temp*temp;
                cin>>temp;
                totalAy+=temp;
                totalAySquare+=temp*temp;
            }
            for(int i=0;i<B;i++)
            {
                cin>>temp;
                bx.push_back(temp);
                cin>>temp;
                by.push_back(temp);
            }
            long long x,y;
            x=totalAx/A;          
            y=totalAy/A;
            ans=min(ans,calAll(x,y+1));
            ans=min(ans,calAll(x+1,y));
            ans=min(ans,calAll(x+1,y+1));
            ans=min(ans,calAll(x,y));
    
            cout<<"Case #"<<Case<<": "<<ans<<endl;
        }
    }
    

      代码来自:http://www.cnblogs.com/tjsudys/p/4436433.html

    态度决定高度,细节决定成败,
  • 相关阅读:
    SAP MM模块教程(1)— 概述
    CodeSmith Generator
    EasyUI 左侧 tree 右侧 DataGrid模板
    C# 数据库访问公共类
    Easyui datagrid toolbar 模板
    EasyUI combogrid 更新查询参数 queryParams 重新加载
    Jenkins的搭建与使用
    Idea2020激活,全网最新教程(各版本通用),亲测2089!!!
    阿里云盘开启“个人云种子用户报名
    尚硅谷Java互联网大厂面试题第三季,1024干货
  • 原文地址:https://www.cnblogs.com/lxk2010012997/p/4437121.html
Copyright © 2011-2022 走看看