历届试题 邮局
时间限制:1.0s 内存限制:256.0MB
问题描述
C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。
现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。
现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。
输入格式
输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。
接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。
接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。
在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。
接下来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
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。
对于60%的数据,1<=m<=20;
对于100%的数据,1<=n<=50,1<=m<=25,1<=k<=10。
dfs做的,40分,后面几组数据都超时了,代码贴出来以后来改正
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF 1000000000
const int maxn=52;
int n,m,k;
struct node{
int x,y;
node(int x=0,int y=0):x(x),y(y){}
};
node user[maxn]; //居民
node yj[maxn]; //邮局
int Min;
int tmp[maxn]; //临时保存编号
int bianhao[maxn]; //保存最终编号
int Min_1(int i){
int cnt=INF;
for(int j=0;j<k;j++){
int x1=user[i].x-yj[tmp[j]].x;
int y1=user[i].y-yj[tmp[j]].y;
cnt=min(cnt,(int)sqrt(x1*x1+y1*y1));
}
return cnt;
}
void dfs(int cur){ //邮局个数
if(cur==k){
int sum=0;
for(int i=0;i<n;i++){
int min1=Min_1(i);
sum+=min1;
}
if(sum<Min){
Min=sum;
for(int i=0;i<k;i++)
bianhao[i]=tmp[i];
}
return ;
}
for(int i=cur;i<m;i++){
if(cur+m-i<k)break; //剪枝
tmp[cur]=i;
dfs(cur+1);
}
}
int main(){
while(scanf("%d%d%d",&n,&m,&k)==3){
for(int i=0;i<n;i++)
scanf("%d%d",&user[i].x,&user[i].y);
for(int i=0;i<m;i++)
scanf("%d%d",&yj[i].x,&yj[i].y);
Min=INF;
dfs(0);
printf("%d",bianhao[0]+1);
for(int i=1;i<k;i++)
printf(" %d",bianhao[i]+1);
printf("\n");
}
return 0;
}