学校要选择一个地方作为超市的位置,学校每个有K个部门,每个部门去超市的频率不一样,要求在可以设置的地点中选择一个最优的地点

来源:互联网 发布:网络信息发布平台 编辑:程序博客网 时间:2024/05/01 17:22

来源于一次课程设计,课设源码位置:https://github.com/treeandgrass/Algorithm-Course-Design

2.7.1题目描述

学校要选择一个地方作为超市的位置,学校每个有K个部门,每个部门去超市的频率不一样,要求在可以设置的地点中选择一个最优的地点。

1)设计核心算法,计算出超市可选位置和最优位置

2)已图像化界面的方式显示学校超市可选点和最优位置,显示学校超市和部门之间的路径和距离。

2.7.2程序使用说明

Java version:1.8.0_111

IDE:eclipse

直接编译Graph.java,然后运行即可

2.7.3简要分析和设计

算法步骤可以分为如下:

1)将部门和超市之间的通路转化为矩阵的形式,在程序中使用二维数组的形式表示,例如将部门和商店作为节点,然后可以把整个问题抽象成一个加权无向图的问题,A表示图中每个顶点之间的通路。A(i,j)表示点i,j之间的距离

2)使用floyd方法计算超市节点到每个部门之间的最短距离

3)在步骤2)的基础上计算每个超市到所有部门的花费。

Floyd算法伪代码:

输入:权重矩阵W[1...n,1...n],权重为每两个点之间的距离

输出:每两个点之间的最短距离矩阵D[1...n,1...n]

Floyd(W[1...n,1...n])

D<—W

For k<—1  to  n  do

For i <—1  to  n  do

For  j <— 1 to  n  do

D[i,j]=min( D(i,j),D[i,k]+D[k,j] )

Return  D

 

计算超市到各个部门之间的距离使用加法模型。设所有超市的点为P=(p1,p2,...,pk)

所有部门点为S=(s1,s2,....,sn),超市pk到所有部门的代价为Cost(pk),部门到超市的频率为F[1..k,1....n],F(k,i)表示部门i到超市k的频率,则可以得到如下计算式:

 

由上述不走计算出了各个商店到部门之间的距离。使用Floyd方法计算的过程中同时记录下了每两个点之间路径的中间点。然后再图像界面上画出整个图,在将超市和部门之间的路径用红色标识。并且在超市标识旁标识出相应大代价。

2.7.4测试用例

权重矩阵W:{{0,4,7,5,12},{4,0,5,6,9},

{7,5,0,-1,10},{5,6,-1,0,9},

{12,9,10,9,0}}

超市和部门名字数组:{"办公区1","超市选址1","超市选址2","办公区2","办公区3"}

超市和部门对应坐标:

{{50,50},{200,100},{80,400},{300,30},{400,300}}

超市ID,在{1,2}部门ID{0,3,4}

结果:

 

2.7.5源代码

package four.three;

 

import java.awt.Color;

import java.awt.Graphics;

import java.util.ArrayList;

import java.util.HashMap;

 

import javax.swing.JFrame;

import javax.swing.JPanel;

 

/**

 * 无向图

 * @author ym

 *

 */

public class Graph extends JPanel{

 

/**

 * 序列号

 */

private static final long serialVersionUID = 1L;

//记录图中各店之间通路的权重值,存在通路权重值为正,否则为负

private int[][] w = null;

//记录超市的Id

private int[] market = null;

//记录单位Id

private int[] office=null;

//记录地点名字

String[] nameList = null;

//记录超市位置

int[][] position=null;

//记录单位去超市的频度

private int[] freq = null;

//记录个点之间的最短距离

private int[][] res = null;

//存储超市选点对应花费

HashMap<Integer,Integer> dotCostMap = null;

//记录各店之间的中间点

@SuppressWarnings("rawtypes")

private ArrayList[][] listMatrix = null;

//存储按照花费由小到大的排列的点

ArrayList<Integer> orderDots = null;

public Graph(int[][] w,int[] market,int[] office,int[] freq,String[] nameList,int[][] position){

this.w=w;

this.market=market;

this.office=office;

this.freq=freq;

this.nameList=nameList;

this.position=position;

this.res=new int[w.length][w[0].length];

this.listMatrix = new ArrayList[w.length][w[0].length];

dotCostMap = new HashMap<Integer,Integer>();

//计算可选点

orderDots = OptionalDot();

}

/**

 * 使用Floyd算法计算超市和

 * 单位之间的最短距离

 */

@SuppressWarnings("unchecked")

public void floyd(){

//初始化结果值

for(int i=0;i<res.length;i++){

for(int j=0;j<res[i].length;j++){

res[i][j]=w[i][j];

}

}

//Floyd 方法

for(int k=0;k<w.length;k++){

for(int i=0;i<w.length;i++){

for(int j=0;j<w[0].length;j++){

//同一点结束本次计算

if(i==j){

continue;

}

//存储两点间的点

listMatrix[i][j]=new ArrayList<Integer>();

int tempResult = -1;

if(res[i][k]>0&&res[k][j]>0){

tempResult = res[i][k]+res[k][j];

}

//计算K为i j中间点的情况

if(tempResult>0){

if(res[i][j]<0||(tempResult<res[i][j]&&res[i][j]>0)){

res[i][j]=tempResult;

//将i k的中间点加入到集合

if(listMatrix[i][k]!=null){

ArrayList<Integer> temp = listMatrix[i][k];

for(Integer value:temp){

listMatrix[i][j].add(value);

}

}

//将 k j的中间点加入到集合

if(listMatrix[k][j]!=null){

ArrayList<Integer> temp = listMatrix[k][j];

for(Integer value:temp){

listMatrix[i][j].add(value);

}

}

//加入中间点K

listMatrix[i][j].add(k);

}

}

}

}

}

}

 

/**

 * 获取优先顺序后的超市可选点

 * @return

 */

public ArrayList<Integer> OptionalDot(){

//调用Floyd方法计算超市和单位之间的最短距离

floyd();

//存储按照花费由小到大的排列的点

ArrayList<Integer> dots = new ArrayList<Integer>();

//使用插入排序

for(int i=0;i<market.length;i++){

//记录点

int cost=0;

//计算超市对应花费

for(int k=0;k<office.length;k++){

cost+=res[market[i]][office[k]]*freq[k];

}

//加入点和花费的映射

dotCostMap.put(market[i],cost);

 

//加入

dots.add(market[i]);

 

for(int j=dots.size()-1;j>0;j--){

//记录要比较的两个超市Id

int MID1 = dots.get(j);

int MID2 = dots.get(j-1);

if(dotCostMap.get(MID1)<dotCostMap.get(MID2)){

int temp = dots.get(j);

dots.set(j, dots.get(i));

dots.set(j-1,temp);

}

}

}

return dots;

}

@SuppressWarnings("unchecked")

@Override

protected void paintComponent(Graphics g) {

super.paintComponent(g);

//画超市点

for(int i=0;i<market.length;i++){

//X坐标

int X = position[market[i]][0];

//Y坐标

int Y = position[market[i]][1];

//获得这个点的名字

String name=nameList[market[i]];

//获取超市到所有点的花费

String cost = "Cost:"+dotCostMap.get(market[i]);

g.fillOval(X-8, Y-8,16,16);

g.drawString(name, X-16,Y-16);

g.drawString(cost, X, Y+20);

}

//画超市点

for(int i=0;i<office.length;i++){

//X坐标

int X = position[office[i]][0];

//Y坐标

int Y = position[office[i]][1];

//获得这个点的名字

String name=nameList[office[i]];

g.fillOval(X-8, Y-8,16,16);

g.drawString(name, X-16,Y-16);

}

//对图中的各点连线

for(int i=0;i<w.length;i++){

for(int j=0;j<w[0].length;j++){

//同一点停止此次操作

if(i==j){

continue;

}

if(w[i][j]>0){

//获取两点的坐标

int IX = position[i][0];

int IY = position[i][1];

int JX = position[j][0];

int JY =position[j][1];

//路径权重

int weight=w[i][j];

g.drawLine(IX, IY, JX, JY);

//标出线段的权重

g.drawString(""+weight,(IX+JX)/2,(IY+JY)/2);

}

}

}

 

//设置线为红色

g.setColor(Color.RED);

//将超市到各个办公地区的点描红

for(int i=0;i<orderDots.size();i++){

for(int j=0;j<office.length;j++){

//获取i j两点间的路径

ArrayList<Integer> path = listMatrix[orderDots.get(i)][office[j]];

//路径的起始点

int start = orderDots.get(i);

//路径的终止点

int end=office[j];

for(int middle:path){

//获取两点的坐标

int startX = position[start][0];

int startY = position[start][1];

int middleX=position[middle][0];

int middleY=position[middle][1];

//描线

g.drawLine(startX,startY,middleX,middleY);

//更新开始点

start = middle;

}

int startX =position[start][0];

int startY =position[start][1];

int endX=position[end][0];

int endY = position[end][1];

//描绘路径中与结束点的连线

g.drawLine(startX,startY,endX,endY);

}

}

}

public int[][] getW() {

return w;

}

public void setW(int[][] w) {

this.w = w;

}

public int[] getMarket() {

return market;

}

public void setMarket(int[] market) {

this.market = market;

}

public int[] getOffice() {

return office;

}

public void setOffice(int[] office) {

this.office = office;

}

public int[] getFreq() {

return freq;

}

public void setFreq(int[] freq) {

this.freq = freq;

}

public int[][] getRes() {

return res;

}

public void setRes(int[][] res) {

this.res = res;

}

 

@SuppressWarnings("rawtypes")

public ArrayList[][] getListMatrix() {

return listMatrix;

}

 

@SuppressWarnings("rawtypes")

public void setListMatrix(ArrayList[][] listMatrix) {

this.listMatrix = listMatrix;

}

public HashMap<Integer, Integer> getDotCostMap() {

return dotCostMap;

}

 

public void setDotCostMap(HashMap<Integer, Integer> dotCostMap) {

this.dotCostMap = dotCostMap;

}

public static void main(String[] args) {

//权重值

int[][] w={{0,4,7,5,12},{4,0,5,6,9},

{7,5,0,-1,10},{5,6,-1,0,9},

{12,9,10,9,0}};

String[] nameList = {"办公区1","超市选址1","超市选址2","办公区2","办公区3"};

//对应坐标

int[][] position = {{50,50},{200,100},{80,400},{300,30},{400,300}};

//超市Id

int[] market = {1,2};

//单位Id

int[] office={0,3,4};

//频度

int[] freq = {4,7,11};

Graph graph = new Graph(w, market, office, freq,nameList,position);

//记录超市Id

// ArrayList<Integer> dots =graph.OptionalDot();

JFrame JF = new JFrame("学校超市选址问题");

JF.setSize(600,600);

JF.setLocationRelativeTo(null);

JF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JF.add(graph);

JF.setVisible(true);

/*for(Integer value:dots){

System.out.println("点:"+value+"  花费:"+graph.getDotCostMap().get(value));

}

for(int i=0;i<market.length;i++){

for(int j=0;j<office.length;j++){

System.out.println(market[i]+"与"+office[j]+"点间路径:");

//获取i j间的路径

ArrayList<Integer> path = graph.getListMatrix()[market[i]][office[j]];

for(int k:path){

System.out.print(" "+k);

}

}

}*/

}

}

0 0
原创粉丝点击