2013数据结构课程设计之便利店选址(暴力枚举和随机函数两种做法)

[问题描述]

某小区决定在小区内部建一家便利店,现小区内部共有八栋楼,它们的地理坐标分别为:(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)八栋楼的居民人数为权重,应该方便大多数人,实现总体最优。


先是暴力找点的方法。


解题思路:自己开始想的就是暴力枚举,先找大范围,再找小范围。做这个题目就想到了的warmup2的1002题,但当时就是A不了。思路很简单,一步步地精确范围。先把整个地方划分成10*10的方格,再在里面找哪个最小,然后继续10*10每次都这样划分,精度确定跳出循环即可。详解见代码。


代码:

 

#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
int n; //n栋楼
double minx,miny,maxx,maxy,px,py;  //找到四个边界
double ansx,ansy,sum;  //最后的结果
struct mq
{
    double x;
    double y;
    int peo;
};
mq node[1005];

double cal(double px,double py)  //计算值
{
    int i;
    double sum=0;
    for(i=0;i<n;i++)
        sum+=sqrt((px-node[i].x)*(px-node[i].x)+(py-node[i].y)*(py-node[i].y))*node[i].peo;
    return sum;
}

void solve()
{
     double i,j;
     double fenx=maxx-minx;  //把x分成若干份
     double feny=maxy-miny;  //把y分成若干份

     while(fenx>0.01&&feny>0.01)  //暴力找点
     {
        fenx/=10.0,feny/=10.0;
        for(i=minx;i<=maxx;i+=fenx)
            for(j=miny;j<=maxy;j+=feny)
            {
                 double tmp=cal(i,j);
                 if(tmp<sum)
                 {
                     sum=tmp;
                     ansx=i;
                     ansy=j;
                 }
            }
        minx=ansx-fenx;
        miny=ansy-feny;
        maxx=ansx+fenx;
        maxy=ansy+feny;
     }
}

int main()
{
    int i;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    while(~scanf("%d",&n))  //n栋楼
    {
        scanf("%lf%lf%d",&node[0].x,&node[0].y,&node[0].peo);
        minx=maxx=node[0].x; miny=maxy=node[0].y;
        //找到四个边界
        for(i=1;i<n;i++)
        {
            scanf("%lf%lf%d",&node[i].x,&node[i].y,&node[i].peo);
            if(node[i].x<minx) minx=node[i].x;
            if(node[i].x>maxx) maxx=node[i].x;
            if(node[i].y<miny) miny=node[i].y;
            if(node[i].y>maxy) maxy=node[i].y;
        }

        sum=100000000;
        solve();
        cout<<"便利店选址坐标为:"<<endl;
        cout<<"x: "<<ansx<<"   "<<"y: "<<ansy<<endl;
        cout<<"最优解为: "<<sum<<endl;
    }
    return 0;
}

/*
8
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
便利店选址坐标为:
x: 16.5404   y: 27.4362
最优解为: 5146.85
*/


 

然后就是LCM说的随机算法,也没想到那一块,被他一说是有些道理,但是点的范围一扩大的话,就没那么准确了。

随机算法,我是直接采用的随机数然后%lenth,区间宽度,相当于0~lenth-1。随机函数对范围要求比较严格吧,范围如果太大,随机也没用了。具体实现见代码:

代码:

 

#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
int n; //n栋楼
struct mq
{
    double x;
    double y;
    int peo;
};
mq node[1005];

double cal(double px,double py)  //计算值
{
    int i;
    double sum=0;
    for(i=0;i<n;i++)
        sum+=sqrt((px-node[i].x)*(px-node[i].x)+(py-node[i].y)*(py-node[i].y))*node[i].peo;
    return sum;
}
int main()
{
    int i;
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    double minx,miny,maxx,maxy,px,py;  //找到四个边界
    double ansx,ansy;  //最后的结果
    while(~scanf("%d",&n))  //n栋楼
    {
        scanf("%lf%lf%d",&node[0].x,&node[0].y,&node[0].peo);
        minx=maxx=node[0].x; miny=maxy=node[0].y;
        //找到四个边界
        for(i=1;i<n;i++)
        {
            scanf("%lf%lf%d",&node[i].x,&node[i].y,&node[i].peo);
            if(node[i].x<minx) minx=node[i].x;
            if(node[i].x>maxx) maxx=node[i].x;
            if(node[i].y<miny) miny=node[i].y;
            if(node[i].y>maxy) maxy=node[i].y;
        }

        minx*=100,maxx*=100,miny*=100,maxy*=100;  //边界扩大一百倍
        //找到边界了就可以随机了
        int lenx,leny;
        lenx=ceil(maxx-minx),leny=ceil(maxy-miny);
        double sum=1000000000;
        srand((unsigned)time(NULL));  //播种
        for(i=1;i<=500000;i++) //随机50W次
        {
            px=rand()%lenx+minx;
            py=rand()%leny+miny;
            px/=100.0;
            py/=100.0;
            double tmp=cal(px,py);
            if(tmp<sum)
            {
                sum=tmp;
                ansx=px;
                ansy=py;
            }
        }
        cout<<"便利店选址坐标为:"<<endl;
        cout<<"x: "<<ansx<<"   "<<"y: "<<ansy<<endl;
        cout<<"最优解为: "<<sum<<endl;
    }
    return 0;
}

/*
8
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
便利店选址坐标为:
x: 16.56   y: 27.44
最优解为: 5146.85
*/


 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在解决GIS选址问题时,需要考虑以下几个方面的数据和设计思路: 1. 地理空间数据:GIS选址需要获取相关地理空间数据,包括地形、地势、水源、土地利用、道路交通等,这些数据可以帮助确定适宜的选址区域。 2. 市场数据:了解目标市场的规模、分布以及竞争情况等市场数据,可以帮助确定最佳选址位置,避免激烈竞争的地区或缺乏市场需求的地区。 3. 人口数据:获取选址区域的人口密度、人口结构、人口增长趋势等数据,可以帮助确定潜在客户群体的分布和规模,从而为选址决策提供依据。 4. 基础设施数据:了解选址区域的基础设施建设情况,包括交通便利程度、水电燃气供应等,可以帮助评估选址的可行性和成本。 5. 环境数据:考虑选址区域的环境质量、生态保护等因素,包括空气质量、水质、土壤污染等,以确保选址的可持续性和环保性。 在设计思路方面,可以采用以下方法: 1. 空间分析:借助GIS技术进行空间分析,对不同地理要素进行综合评估,确定最佳选址。 2. 多指标综合评价:根据不同的选址要求,建立评价指标体系,并赋予不同权重,然后进行综合评价,选出最优选址。 3. 相似性分析:通过比较选址区域与已有成功案例的相似性,借鉴成功经验,提高选址决策的精确性。 4. 可视化展示:利用GIS技术将各种数据在地图上进行可视化展示,使决策者能够直观地了解选址情况,并进行决策分析。 总之,解决GIS选址问题需要充分获取和分析各类数据,结合合适的设计思路和技术工具进行综合评价和决策,以实现最佳选址结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值