一共有m个邮局从中选出k个邮局,对每个邮局我们有两种选择,一:选择这个邮局。二:不选择这个邮局。很显然我们直接用深搜(dfs)就行。(这里不明白dfs的也没关系,你可以看代码自己思考一下就明白了)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
struct node {
int x,y;
};
node A[51];//记录村民坐标
node B[26];//记录邮局坐标
double l[51][26];//l[i][j]是 i号村民到j号邮局的距离
double dp[51];//dp[i]记录当前选择的所有邮局中,i到所有选择的邮局中的最短的距离
// 既假设选择了 1号和2号 i到1 的距离为3 ,i到2的距离为4,那么所有选择的邮局分别是1,和2,那么
//dp[i]就等于其中最小的哪一个既dp[i]=1;
int n,m,k;
double MAXV=10000001;
vector<int> ve;//存放最佳的邮局号码
vector<int> v;//临时的邮局号码,再dfs里面用到
// index 记录当前的邮局号码,ans记录选择了几个邮局了,
//sum记录村民到自己家最近的邮局的距离最小的和
//dp[i]记录当前选择的邮局中i号村民到选择的邮局的最短距离
void dfs(int index,int ans,double sum,double dp[]){
if(ans==k){//函数的终点 即选择了K个数了
if(sum<MAXV){
ve=v;
MAXV=sum;
return ;
}
return;
}
if(index>m||ans>k) return ;//这个终点不能再if(ans==k)前面 因为当index==m+1时正好有ans==k,
// 那就不能执行if(ans==k)了
double f[56];//新建一个数组f 以为对一个邮局我们可以选择也可以不选择,如果不选择那么
//dp[i]就保持原样 不能改变
for(int i=1;i<=n;i++) {
if(dp[i]>l[i][index])f[i]=l[i][index];//改变f[i]
else f[i]=dp[i];
};
double num=0;
for(int i=1;i<=n;i++) num+=f[i];
v.push_back(index);//选择该邮局则把邮局的号码存进去
dfs(index+1,ans+1,num,f);//选择该邮局继续往下执行 dp的位置换成f因为我们选择了该邮局所以要用f
v.pop_back();// 不选择该邮局则把该邮局踢出去
dfs(index+1,ans,sum,dp);//注意这里仍然时dp以为我们不选择该邮局则dp不用更新
}
int main(){
fill(dp,dp+51,1000001);//把距离初始化成一个特别大的数
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%d%d",&A[i].x,&A[i].y);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&B[i].x,&B[i].y);
for(int j=1;j<=n;j++){
l[j][i]=sqrt(pow(A[j].x-B[i].x,2)+pow(A[j].y-B[i].y,2) );
}
}
dfs(1,0,0,dp);
for(int i=0;i<ve.size();i++){
printf("%d ",ve[i]);
}
return 0;
}