zoukankan      html  css  js  c++  java
  • 试题 历届试题 邮局(dfs好题)

    问题描述
      C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。

      现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。
    输入格式
      输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。
      接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。
      接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。
      在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。
    输出格式
      输出一行,包含k个整数,从小到大依次表示你选择的备选邮局编号。(备选邮局按输入顺序由1到m编号)
    样例输入
    5 4 2
    0 0
    2 0
    3 1
    3 3
    1 1
    0 1
    1 0
    2 1
    3 2
    样例输出
    2 4
    数据规模和约定
      对于30%的数据,1<=n<=10,1<=m<=10,1<=k<=5;
      对于60%的数据,1<=m<=20;
      对于100%的数据,1<=n<=50,1<=m<=25,1<=k<=10。
    思路
    需要的数据,居民坐标,邮局坐标,每个居民到所有邮局的距离range。
    维护一个居民到最近的邮局距离的数组length,如果有边有更新,证明该邮局可选。
    每个邮局都有选和不选,两种选择,分别进行dfs。
    当已选定k个邮局时比较总距离是否有减小,有的话进行更新,存储邮局的序号用一个vector即可。
    直接暴力只能得到80分,需要做一些剪枝。
    1.当到第pos个邮局时,后面所有的邮局全选的情况仍不满足条件,可直接跳出。
    2.当第pos个邮局无法松弛距离,做一个标记,之后只走不选择的那条路。
    #include<bits/stdc++.h>
    using namespace std;
    struct node{
        int x, y;
    }host[55],post[55];
    int n,m,k;
    double lenth[55],range[55][55],vis[55];
    const int inf=0x3f3f3f;
    double maxx=0x3f3f3f;
    vector<int>vex;
    void dfs(int pos,double sum,int num,vector<int>v){
        if(num+m-pos+1<k)return ;///pruning
        if(num==k){
            if(sum<maxx){
                maxx=sum;
                vex=v;
            }
            return ;
        }
        dfs(pos+1,sum,num,v);///not to bulid
        if(vis[pos])return ;
        double temp[55];
        memcpy(temp,lenth,sizeof(temp));///temp object
        int flag=0;
        for(int j=1;j<=n;j++){
            if(range[pos][j]<lenth[j]){///update
                lenth[j]=range[pos][j];
                flag=1;
            }
        }
        sum=0;
        for(int k=1;k<=n;k++){
            sum+=lenth[k];
        }
        if(flag){///bulid
            v.push_back(pos);
            dfs(pos+1,sum,num+1,v);
            v.pop_back();
            memcpy(lenth,temp,sizeof(lenth));///fight off the effect
        }
        else vis[pos]=1;
    }
    double dis(node a,node b){
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&host[i].x,&host[i].y);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&post[i].x,&post[i].y);
            for(int j=1;j<=n;j++){
                range[i][j]=dis(post[i],host[j]);
            }
        }
        for(int i=1;i<=n;i++){
            lenth[i]=inf;
        }
        dfs(1,0,0,vex);
        sort(vex.begin(),vex.end());
        for(vector<int>::iterator it=vex.begin();it!=vex.end();it++){
            cout<<*it<<" ";
        }
        return 0;
    }

     

  • 相关阅读:
    HTML元素事件说明
    JQuery基本方法介绍和使用
    Eclipse设置注释模板
    AJAX回调(调用后台方法返回数据)
    Hibernate常用增删改查方法
    C memset
    PAT-Top1002. Business (35)
    PAT-Top1001. Battle Over Cities
    聂老师的考验(反向bfs)
    CSUST选拔赛题解
  • 原文地址:https://www.cnblogs.com/mohari/p/13405354.html
Copyright © 2011-2022 走看看