便利店选址问题

Update:

1、C code refactoring

2、Add Java code


【问题描述】

某小区决定在小区内部建一家便利店,现小区内部共有八栋楼,它们的地理坐标分别为:(10,20)、(30,34)、(19,25)、(38,49.1)、(9,38.1)、(2,34)、(5,8)、(29,48)。同时,其中的住户人数分别为:30, 45, 28, 8, 36, 16, 78, 56。为了方便更多的住户购物,要求实现总体最优,请问便利店应该建立在哪里?

提示

1)便利店无论选址何处,八栋楼的居民均可直接到达,即八栋楼与便利店均相邻,且距离为直线距离;

2)八栋楼的居民人数为权重,应该方便大多数人,实现总体最优。


【解题思路】

通过对设计要求的分析。程序将由以下几个功能模块构成。

  •   地址坐标

  •   距离计算函数

  •   近似最优解求解模块

 

【算法描述】

1.地址坐标:

首先让我们假设出一张地图:为了简便,我们用A、B、C、D、E、F、G、H表示小区内部的八栋楼,设P为便利店。

我们将地图分割成若干等份:A、B、C、D、E、F、G、H分别在网格的格点上。

确立坐标:坐标原点为(0,0),设A点坐标为(X0,Y0),B点坐标为(X1,Y1),C点坐标为(X2,Y2),D点坐标为(X3,Y3),E点坐标为(X4,Y4),F点坐标为(X5,Y5),G点坐标为(X6,Y6),H点坐标为(X7,Y7),P点坐标为(Xp,Yp)。


2.距离计算函数:

由此,我们不难设计一个函数计算出AP、BP、CP、DP、EP、FP、GP、HP的长度。在不考虑权重的情况下,只要八者之和最短,则P点就为便利店所在地。但是,由于还要考虑人数对选址的影响,所以对数据进行如下处理:XA=X0*权重A;XB=X1*权重B;XC=X2*权重C;XD=X3*权重D;XE=X4*权重E;XF=X5*权重F;XG=X6*权重G;XH=X7*权重H;然后再从中选出使八者之和最小的P点!


3.近似最优求解模块:

由于P点的坐标是不确定的,所以P的值是变化的。考虑到实际情况下,超市不可能占地面积只有一个点。所以我们将P的精度取到1米,让D的坐标以1米为步长,其X,Y轴分别加1与各个单位求距离。


【代码实现】

1、C语言版

#include<stdio.h>
#include<math.h>

#define N 8

//结构体定义
struct chooseLocale

{

	double x;

	double y;

	int w;

	double xp;

	double yp;

} location[N];

double  g_minX=0;
double g_maxX=0;
double g_minY=0;
double g_maxY=0;
double g_minSum=30000;
double g_shopX=0;
double g_shopY=0;
int g_iCount=0;


double get_length(double x,double y,double x1,double y1);
void getEdgelocation();
void inputHouselocation();
void getShoplocation();


int main()

{

	inputHouselocation();
	getEdgelocation();
	getShoplocation();

	printf("count=%d\n",g_iCount);//打印sum计算次数
	printf("minsum=%lf\n",g_minSum);
	printf("计算出便利店建立的地理坐标为:\nlocation(%lf,%lf)\n",g_shopX,g_shopY);
	return 0;

}

double get_length(double x,double y,double x1,double y1) {


	return(sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)));
}
/*
  输入各个单位坐标
 (10,20,30) , (30,34,45) , (19,25,28) , (38,49.1,8) , (9,38.1,36) , (2,34,16) , (5,8,78) , (29,48,56)
*/
void inputHouselocation() {
	for(int i=0; i<N; i++) {
		printf("Please input House %d locationInfo :\n",i);
		scanf("%lf%lf%d",&location[i].x,&location[i].y,&location[i].w);
	}
}
/*
  找到八个单位中坐标的边缘点,以缩小搜索范围。
*/
void getEdgelocation() {

	for(int i=0; i<N; i++) {
		if(location[i].x<g_minX) {
			g_minX=location[i].x;
		} else {
			g_maxX=location[i].x;
		}
		if(location[i].y<g_minY) {
			g_minY=location[i].y;
		} else {
			g_maxY=location[i].y;
		}

	}
}

void getShoplocation() {
	struct chooseLocale	cl;
	double len[8]= {0};
	double sum=0;


	for(cl.xp=g_minX; cl.xp<=g_maxX; cl.xp++)

	{

		for(cl.yp=g_minY; cl.yp<=g_maxY; cl.yp++)

		{


			for(int i=0; i<N; i++)

			{

				len[i]=get_length(location[i].x,location[i].y,cl.xp,cl.yp);

				len[i]=len[i]*location[i].w;

				sum=sum+len[i];
				g_iCount++;

			}

			if(sum<g_minSum) {

				g_minSum=sum;
				g_shopX=cl.xp;
				g_shopY=cl.yp;

			}
			sum=0;

		}


	}
}


 
 2、Java版 
  
 

LocationInfo.java

/**
 * @author john
 * @created 2016-1-28
 */
public class LocationInfo
{
private double mLocationX=0;
private double mLocationY=0;
private int mWeight=0;
public double getLocationX()
{
	return mLocationX;
}
public void setLocationX(double locationX)
{
	mLocationX = locationX;
}
public double getLocationY()
{
	return mLocationY;
}
public void setLocationY(double locationY)
{
	mLocationY = locationY;
}
public int getWeight()
{
	return mWeight;
}
public void setWeight(int weight)
{
	mWeight = weight;
}

}


ShopVo.java

/**
 * @author john
 * @created 2016-1-28
 */
public class ShopVo
{
	private double mDistanceMinSum = 0;
	private double[] mShopLocation = { 0, 0 };
	private int mCount = 0;

	public double getDistanceMinSum()
	{
		return mDistanceMinSum;
	}

	public void setDistanceMinSum(double distanceMinSum)
	{
		mDistanceMinSum = distanceMinSum;
	}

	public double[] getShopLocation()
	{
		return mShopLocation;
	}

	public void setShopLocation(double[] shopLocation)
	{
		mShopLocation = shopLocation;
	}

	public int getCount()
	{
		return mCount;
	}

	public void setCount(int count)
	{
		mCount = count;
	}

}

CalculateShopLocale.java

import java.util.List;

/**
 * @author john
 * @created 2016-1-28
 */
public class CalculateShopLocale
{
	private int mHouseNum = 0;
	private Double[] edgeMinLocation = new Double[2];
	private double[] edgeMaxLocation = { 0, 0 };
	private double[] distances = { 0,0};
	private List<LocationInfo> mLocationInfoList = null;
	/**
	 * 估算的最小距离
	 */
	private double distanceMinSum = 0;

	/**
	 * 构造函数初始化 mHouseNum , mLocationInfoList , distanceMinSum
	 * 
	 */
	public CalculateShopLocale(int mHouseNum, List<LocationInfo> mLocationInfoList, double distanceMinSum)
	{
		
		this.mHouseNum = mHouseNum;
		this.mLocationInfoList = mLocationInfoList;
		this.distanceMinSum = distanceMinSum;
		
	}

	/**
	 * 获取两地距离
	 */
	private double getTwoPositionDistance(double x, double y, double newX, double newY)
	{
		// TODO Auto-generated method stub
		double distance = Math.sqrt(Math.pow(newX - x, 2)+Math.pow(newY - y, 2));
		return distance;
	}

	/**
	 * 找到所有位置中坐标的边缘点,以缩小搜索范围
	 */
	private void getEdgeLocation()
	{

		if (mLocationInfoList != null)
		{
			edgeMinLocation[0] = mLocationInfoList.get(0).getLocationX();
			edgeMinLocation[1] = mLocationInfoList.get(0).getLocationY();
			for (int i = 0; i < mHouseNum; i++)
			{
				if (mLocationInfoList.get(i).getLocationX() < edgeMinLocation[0])
				{
					edgeMinLocation[0] = mLocationInfoList.get(i).getLocationX();
				}
				else
				{
					edgeMaxLocation[0] = mLocationInfoList.get(i).getLocationX();
				}
				if (mLocationInfoList.get(i).getLocationY() < edgeMinLocation[1])
				{
					edgeMinLocation[1] = mLocationInfoList.get(i).getLocationY();
				}

				else
				{
					edgeMaxLocation[1] = mLocationInfoList.get(i).getLocationY();
				}

			}
		}

	}

	/**
	 * 获取便利店最佳选址位置,并打印出该位置到所有住户最小距离和,同时打印出计算次数
	 */
	public void getShopLocation(ShopVo sv)
	{
		System.out.println("CalculateShopLocale <<< mList = "+mLocationInfoList);
		getEdgeLocation();

		double distanceSum = 0;
		double[] shopLocation = { 0, 0 };
		int iCount = 0;

		for (double x = edgeMinLocation[0]; x <= edgeMaxLocation[0]; x++)

		{

			for (double y = edgeMinLocation[1]; y <= edgeMaxLocation[1]; y++)

			{

				for (int i = 0; i < mHouseNum; i++)

				{

					distances[i] = getTwoPositionDistance(mLocationInfoList.get(i).getLocationX(), mLocationInfoList.get(i).getLocationY(), x, y);

					distances[i] *= mLocationInfoList.get(i).getWeight();

					distanceSum += distances[i];
					iCount++;

				}

				if (distanceSum < distanceMinSum)
				{
					distanceMinSum = distanceSum;
					shopLocation[0] = x;
					shopLocation[1] = y;
				}
				distanceSum = 0;

			}

		}

		sv.setDistanceMinSum(distanceMinSum);
		sv.setCount(iCount);
		sv.setShopLocation(shopLocation);

	}

}

Main.java

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author john
 * @created 2016-1-28
 */
public class Main
{
	/**
	 * 住户数
	 */
	private static final int HOUSE_NUM = 8;
	private static Scanner sc = new Scanner(System.in);

	/**
	 * 控制台输入住户位置信息参数(x,y,w)
	 * 
	 * (10,20,30) , (30,34,45) , (19,25,28) , (38,49.1,8) , (9,38.1,36) ,
	 * (2,34,16) , (5,8,78) , (29,48,56)
	 * 
	 */
	private static LocationInfo getHouseLocationItem(LocationInfo locationInfo)
	{

		System.out.println("Please input LocationX : ");
		double locationX = sc.nextDouble();

		System.out.println("Please input LocationY : ");
		double locationY = sc.nextDouble();

		System.out.println("Please input weight : ");
		int weight = sc.nextInt();

		locationInfo.setLocationX(locationX);
		locationInfo.setLocationY(locationY);
		locationInfo.setWeight(weight);

		return locationInfo;
	}

	/**
	 * 获取各个位置地理坐标和权值
	 */
	private static List<LocationInfo> getHouseLocationList(LocationInfo locationInfo)
	{
		List<LocationInfo> list = new ArrayList<LocationInfo>();

		for (int i = 0; i < HOUSE_NUM; i++)
		{
			System.out.println("Please input House " + i + " LocationInfo");
			locationInfo = getHouseLocationItem(locationInfo);
			list.add(locationInfo);

		}

		return list;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub

		// 估算的最小距离
		double distanceMinSum = 30000;
		ShopVo shopVo = new ShopVo();

		LocationInfo locationInfo = new LocationInfo();
		List<LocationInfo> mList = getHouseLocationList(locationInfo);
		System.out.println("Main <<< mList = " + mList);

		CalculateShopLocale csl = new CalculateShopLocale(HOUSE_NUM, mList, distanceMinSum);
		csl.getShopLocation(shopVo);
		sc.close();
		System.out.println("计算总次数  : " + shopVo.getCount() + "\n" + "便利店最佳选址位置到所有住户最小距离和  : " + shopVo.getDistanceMinSum() + "\n" + "便利店建立的地理坐标  : " + shopVo.getShopLocation());

	}
}


【运行结果】(代码重构前)

便利店选址问题_第1张图片

你可能感兴趣的:(数据结构,C语言,策略,算法问题)