蓝桥杯 历届试题 邮局(暴力DFS)

46 篇文章 5 订阅

问题描述
  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<=101<=m<=101<=k<=5;
  对于60%的数据,1<=m<=20;
  对于100%的数据,1<=n<=501<=m<=251<=k<=10
//90分代码
#include<bits/stdc++.h>
using namespace std;
const int N=60;
struct node{
	int x,y;
}city[55];
double dist[55][55];//储存每个居民到邮局的距离 
int n,m,k;
vector<int>t,ans;
double maxn=0x3f3f3f3f;
double getd(double a,double b,double c,double d){
	return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
void dfs(int index,int sum){//index列举到哪一个,sum当前选了哪个
    if(index>m||sum>k)return;
	if(sum==k){
		double total=0; 
		for(int i=0;i<n;i++){
			double minx=0x3f3f3f3f;//放在里面 
			
			for(int j=0;j<t.size();j++){
				int e=t[j];
				minx=min(minx,dist[i][e]);
			}
		  total+=minx;//最小距离和 
		}
		if(total<maxn){
			maxn=total;//更新 
			ans=t;
		} 
		return;
	}
     	dfs(index+1,sum);//不选
	
		t.push_back(index);
		dfs(index+1,sum+1);//选 
		t.pop_back();
	} 	
int main(){
	cin>>n>>m>>k;
	for(int i=0;i<n;i++){
		cin>>city[i].x>>city[i].y;
	}
	for(int i=0;i<m;i++){
		int a,b;
		cin>>a>>b;
		for(int j=0;j<n;j++){
			dist[j][i]=getd(city[j].x,city[j].y,a,b);
		}
	}
	dfs(0,0);
	for(int i=0;i<ans.size();i++){
		cout<<ans[i]+1<<' ';
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王子y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值