目录

1 问题描述

2 解决方案

 


1 问题描述

问题描述
  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。

2 解决方案

本题主要考查DFS搜索和剪枝,具体解释请看注释。

具体代码如下:

import java.util.Scanner;

public class Main {
public static int n, m, k;
public static double[][] distance; //distanc[i][j]表示第i个村庄到第j个邮局的直线距离
public static int[] answer; //存放最终选中的k个邮局编号
public static double minSum; //表示选中k个邮局的最小距离和 public void init() {
distance = new double[n + 1][m + 1];
answer = new int[k + 1];
minSum = Double.MAX_VALUE;
} /*
* 参数count:表示已经选中的邮局个数
* 参数current:表示DFS目前遍历到的邮局编号
* 参数minDis:minDis[i]表示村庄i到已选中邮局中的最短距离
* 参数tempAns:存放目前遍历过程中已经选中的邮局编号
*/
public void dfs(int count, int current, double[] minDis, int[] tempAns) {
if(count == k) { //当已经选中k个邮局时
double tempSum = 0;
for(int i = 1;i <= n;i++)
tempSum += minDis[i];
if(tempSum < minSum) {
minSum = tempSum;
for(int i = 1;i <= k;i++)
answer[i] = tempAns[i];
}
return;
} else if(k - count <= m - current && current <= m) { //表示在剩下未选中的邮局个数多于还需要选中的邮局个数
boolean judge = false; //用于判断当前选中的邮局current+1是否符合要求
double[] minDis1 = new double[n + 1]; //用于保存当前minDis数组中值
for(int i = 1;i <= n;i++)
minDis1[i] = minDis[i];
for(int i = 1;i <= n;i++) {
if(minDis[i] > distance[i][current + 1]) {
minDis[i] = distance[i][current + 1];
judge = true;
}
}
tempAns[count + 1] = current + 1;
if(judge == true) //邮局current + 1符合要求,选中个数加1继续搜索
dfs(count + 1, current + 1, minDis, tempAns);
dfs(count, current + 1, minDis1, tempAns); //直接舍弃邮局current+1,进行下一次搜索
}
} public static void main(String[] args) {
Main test = new Main();
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
k = in.nextInt();
test.init();
double[][] point = new double[n + 1][2]; //存放n个村庄的位置坐标
for(int i = 1;i <= n;i++) {
point[i][0] = in.nextDouble(); //村庄横坐标
point[i][1] = in.nextDouble(); //村庄纵坐标
}
for(int j = 1;j <= m;j++) {
double x = in.nextDouble(); //邮局横坐标
double y = in.nextDouble(); //邮局纵坐标
for(int i = 0;i <= n;i++) //计算1~n村庄到邮局j的直线距离
distance[i][j] = Math.sqrt((point[i][0]-x)*(point[i][0]-x) +
(point[i][1]-y)*(point[i][1]-y));
}
int[] tempAns = new int[k + 1];
double[] minDis = new double[n + 1]; //minDis[i]表示第i个村庄到已选中的邮局中的最小距离
for(int i = 1;i <= n;i++)
minDis[i] = Double.MAX_VALUE;//初始化第i个村庄到选中邮局中最小距离为最大值 test.dfs(0, 0, minDis, tempAns);
for(int i = 1;i <= k;i++)
System.out.print(answer[i]+" ");
}
}

参考资料:

1.蓝桥杯历届试题 邮局(DFS)

算法笔记_178:历届试题 邮局(Java)的更多相关文章

  1. 算法笔记_197:历届试题 带分数(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. ...

  2. 算法笔记_177:历届试题 城市建设(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 栋栋居住在一个繁华的C市中,然而,这个城市的道路大都年久失修.市长准备重新修一些路以方便市民,于是找到了栋栋,希望栋栋能帮助他. C市中有 ...

  3. 算法笔记_189:历届试题 横向打印二叉树(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 二叉树可以用于排序.其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树. 当遇到空子树 ...

  4. 算法笔记_186:历届试题 高僧斗法(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 古时丧葬活动中经常请高僧做法事.仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛. 节目大略步骤为:先用粮食(一般是稻米)在地 ...

  5. 算法笔记_184:历届试题 约数倍数选卡片(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 闲暇时,福尔摩斯和华生玩一个游戏: 在N张卡片上写有N个整数.两人轮流拿走一张卡片.要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数 ...

  6. 算法笔记_183:历届试题 九宫重排(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成 ...

  7. 算法笔记_176:历届试题 最大子阵(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大. 其中,A的子矩阵指在A中行和列均连续的一块. 输入格式 输入 ...

  8. 算法笔记_174:历届试题 地宫取宝(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明 ...

  9. 算法笔记_172:历届试题 波动数列(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 观察这个数列: 1 3 0 2 -1 1 -2 ... 这个数列中后一项总是比前一项增加2或者减少3. 栋栋对这种数列很好奇,他想知道长度 ...

随机推荐

  1. 《TD式创新”祸国殃民》

    TD式创新”祸国殃民> 作者:北京邮电大学 阚凯力 (2014年12月16日) 电信业内早就众所周知的TD-SCDMA真相,终于公之于天下.铁的事实是,它从来就不是什么“自主知识产权”,而是西门 ...

  2. 写给在Java和.net中徘徊的新手

    在很多网站上,网友都会问一个相同的问题,到底是学Java还是.net,个有个的见解. 自从.Net问世以来,程序员都很关心的一个问题是「该学Java或.NET」.我也在挣扎,该「该继续Java的研究, ...

  3. C#使用反射加载多个程序集

    当开发插件的时候需要用到反射,在客户端动态加载遍历程序集,并调用每个程序集的方法. 创建一个控制台应用程序,首先设计一个接口: public interface ISay { void SaySth( ...

  4. 转 Objective-C中不同方式实现锁(一)

    为什么需要使用锁,当然熟悉多线程的你,自然不会对它觉得陌生. 那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢? 今天一起来探讨一下Objective-C中几种不同方式实现的锁,在这 ...

  5. C#编程(七)----------命名空间

    命名空间 命名空间的设计目的是为了提供一种让一组名称与其他名称分隔开的方式.在一个命名空间中声明的类的名称与另一个命名空间中声明的相同的类的名称不冲突. 关键字:namespace namespace ...

  6. joel 相关

    1. stack overflow , http://blog.jobbole.com/102810/, stack overflow 提问也是一门学问. 2. tello 类似于 leangoo,一 ...

  7. linux 字符终端terminal下 ftp的配置和启用

    1. ftp组件一般不是linux的自带组件,在ubuntu 12中,就自带了ftp组件 vsftp,而在redhat 9中,就没有自带需要从安装光盘中或下载相应的ftp的rpm包. ~$ sudo ...

  8. 转: gob编解码

    要让数据对象能在网络上传输或存储,我们需要进行编码和解码.现在比较流行的编码方式有JSON,XML等.然而,Go在gob包中为我们提供了另一种方式,该方式编解码效率高于JSON.gob是Golang包 ...

  9. 原生js获取宽高与jquery获取宽高的方法的关系

    说明:1.因为获取高度的情况跟获取宽度的情况一样,所以以下只说获取宽度的情况.  2.以下所说的所有方法与属性所返回的值都是不带单位的.  3.为了方便说明,以下情况采用缩写表示:  obj -> ...

  10. JQuery模仿淘宝天猫魔盒抢购页面倒计时效果

    1.效果及功能说明 通过对时间的控制来告诉用户一个活动还剩多少时间,精确到秒.2.实现原理 首先定义活动的截至的时间,要重年份精确到毫秒,在获得当前的年份到秒钟,在用截至时间,减去现在的时间,剩下的还 ...