MX是世界上第一大传媒娱乐企业,该公司数十年的经营历史中创作了很多经典影片,此外还经营着很多的规模十分宏大世界级的主题娱乐公园。最近MX公司刚和C国X城市达成协定,共同投资建设C国国内唯一一家主题娱乐公园。
主题公园的经营管理部门计划布设m个固定的快餐饮品供应点为游客服务。希望游客游园时,绝对不要受到快餐店补货车工作运行的影响,最好的办法就是绝对不让游客在园中看到补货车,绝对不让游客听到补货车的声音。让游客觉得在园中任何一个餐饮点随时都能买到食品和饮品,能得到无穷无尽的食品和饮品。因此设计团队想把给m个餐饮点供货的通道设置在地下,并在通道内部敷设一定的隔音材料,可是修造地下供货通道的经济代价与通道总长度成正比(每100米修造代价是M万元),花费将是非常巨大的,不过游客至上。
现在设计团队手中已经有了m个餐饮点的坐标位置(x,y)信息,你是设计团队的一员,团队交给你的工作就是规划一个地下通道建设方案,将m个餐饮点都连接起来且总修造代价尽可能地小。
随机生成m个坐标信息验证你的算法和程序,如果最终程序求解的通道规划方案不唯一,则输出其中的任一方案即可(要求m>=30)。
解题代码如下,注释的较为清楚,不在过多阐述。
import java.util.Random;
public class MyPrim {
public static void main(String[] args) {
Random random = new Random();
//随机生成m个坐标信息
int m = random.nextInt(30) + 30;
// int m = 5;
System.out.println("current size = " + m);
//每个店铺与其他店铺的距离
int[][] map = new int[m][m];
for (int i = 0; i < m; i++) {
//当前店铺与之后的所有店铺距离
for (int j = i; j < m; j++) {
if (i == j) {
map[i][j] = 0;
} else {
//每个餐饮店最少隔100米
map[i][j] = random.nextInt(400) + 100;
}
}
//把之前的店铺距离赋值给当前店铺
for (int j = 0; j < i; j++) {
map[i][j] = map[j][i];
}
}
System.out.println(toString(map));
//输出最短距离
System.out.println(startPrim(map, m));
}
private static int startPrim(int[][] map, int m) {
//总距离
int sumDistance = 0;
//已经选择过的餐饮店
int[] selectedMap = new int[m];
//默认都没访问过标记为-1
for (int i = 0; i < m; i++) {
selectedMap[i] = -1;
}
//起点默认为第一个,访问标记为0
selectedMap[0] = 0;
//记录求解的通道规划方案
int startM = 0;
int endM = 0;
//遍历除了第一个之后的每个店铺
for (int i = 0; i < m - 1; i++) {
//当前店铺的最近距离
int minDistance = Integer.MAX_VALUE;
int minMIndex = -1;
//遍历已经选择过得餐饮店
for (int j = 0; j < m; j++) {
if (selectedMap[j] == 0) {
//开始寻找与该店最近的店
int[] currentM = new int[m];
//得到该店与其他未被选择的店的距离
for (int k = 0; k < m; k++) {
if (selectedMap[k] != 0) {
//把二维数组里第j行的数据赋值给当前店铺
currentM[k] = map[j][k];
} else {
currentM[k] = 0;
}
}
//寻找最小值
for (int k = 0; k < m; k++) {
//如果距离不为0,且最小距离大于当前距离
if (currentM[k] != 0 && minDistance > currentM[k]) {
//设置最小距离为当前距离
minDistance = currentM[k];
//记录店铺下标
minMIndex = k;
//记录方案
startM = j;
endM = k;
}
}
//当前这个选择过的餐饮店铺的最近距离店铺找出来后,继续循环找下一个的,直到循环完毕后找到最小的那个店铺
}
}
//设置minMIndex为已选择餐饮店
selectedMap[minMIndex] = 0;
//总距离计算
sumDistance += minDistance;
//输出方案
System.out.println("m" + startM + " is connected to m" + endM+", min distance is "+minDistance+", position["+startM+", "+endM+"]");
}
return sumDistance;
}
//输出所有店铺的距离信息
static String toString(int[][] map) {
StringBuilder s = new StringBuilder();
for (int[] ints : map) {
for (int j = 0; j < ints.length; j++) {
if ((j + 1) == ints.length)
s.append(ints[j]).append("\n");
else
s.append(ints[j]).append(" ");
}
}
return s.toString();
}
}