试题 历届试题 邮局(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;
}

 

posted @ 2020-07-30 17:47  mohari  阅读(306)  评论(0编辑  收藏  举报