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();
}
}