目录

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. 理解JavaScript中BOM和DOM的关系

    JavaScript 有三部分构成,ECMAScript,DOM和BOM,根据宿主(浏览器)的不同,具体的表现形式也不尽相同,IE和其他的浏览器风格迥异.对象是JavaScript最重要的API,包含 ...

  2. SEEprog Serial EEPROM programmer

    Features SEEprog is universal programmer of all types of serial EEPROMs in 8-pin package. SEEprog en ...

  3. Detecting Underlying Linux Distro

    If you are the owner of the system, then you know which Linux is installed and running. This article ...

  4. java基础学习总结——哈希编码

    一.哈希编码

  5. BitmapFactory.Options.inSampleSize 的使用方法

    BitmapFactory.decodeFile(imageFile); 用BitmapFactory解码一张图片时.有时会遇到该错误. 这往往是因为图片过大造成的. 要想正常使用,则须要分配更少的内 ...

  6. spring源码分析之BeanfFactory

    spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了.那么它的原理是什么呢?是怎么实现的呢?下面我来简单的模拟一下spring的机制,相信看完之后 ...

  7. Java 8 中 HashMap 的性能提升

    HashMap是一个高效通用的数据结构,它在每一个Java程序中都随处可见.先来介绍些基础知识.你可能也知 道,HashMap使用key的hashCode()和equals()方法来将值划分到不同的桶 ...

  8. 纯html上下翻滚效果公告板

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. Tomcat6内存不足问题及解决方法

    1.Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,有可能导致系统无法运行.常见的问题是报Tomcat内存溢出错误,Out of Memory(系统内存不足)的异常 ...

  10. html5-语义化标签(一)

    1.什么是语义化标签? 根据内容的结构化(内容化),选择合适标签 2.为什么要语义化 为了在没有css样式的情况下,页面也能很好的呈现出很好的内容结构.代码结构 方便其他设备的解析(屏幕阅读器.盲人阅 ...