蓝桥学习 PREV-24

试题 历届试题 

PREV-24 邮局

问题描述

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

想法:

痛苦深搜,这就是新时代的体罚,超出我的想象范围,虽然有可能是我过于弱智所导致的,但是确实是我的问题,我真的已经尽力了,为什么,最后一个点就是搞不定,世界已经崩塌了。(scanf还是顶啊)

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
struct man{
	double x,y;
}ma[60];
int n,m,d,dd[60],book[60],max1=999999999,qq[60];
double dp[30][60];
void dfs(int node,int k){
	if(node==d){
		double num=0,bfs[60];
		for(int i=0;i<node;i++){
			for(int j=0;j<n;j++){
				if(i==0)bfs[j]=dp[dd[i]][j];
				else bfs[j]=min(bfs[j],dp[dd[i]][j]);
			}
		}
		for(int j=0;j<n;j++){
			num+=bfs[j];
		}
		if(num<max1){
			max1=num;
			for(int i=0;i<node;i++){
				qq[i]=dd[i];
			}
		}
		return;
	}
	for(int i=k;i<=m;i++){
		if(!book[i]){
			book[i]=1;
			dd[node]=i;
			dfs(node+1,i);
			book[i]=0;
		}
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&d);
	for(int i=0;i<n;i++){
		scanf("%lf%lf",&ma[i].x,&ma[i].y);
	}
	for(int i=1;i<=m;i++){
		double q,p;
		scanf("%lf%lf",&q,&p);
		for(int j=0;j<n;j++){
			dp[i][j]=sqrt((q-ma[j].x)*(q-ma[j].x)+(p-ma[j].y)*(p-ma[j].y));
		}
	}
	dfs(0,1);
	for(int i=0;i<d;i++){
		if(i!=0)printf(" "); 
		printf("%d",qq[i]);
	}
	printf("\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值