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

*/


 

 

你可能感兴趣的:(数据结构)