摘 要
学校超市选址问题,一般需要考虑各个单位到它的综合距离最近,并结合不同单位的人员前往超市的频度也不同。其实质是找一个综合权数最小的地点,但是手工求解会造成很大的麻烦。
随着计算机科学的不断进步,为我们找到了计算的途径,大大地节约劳动资源。其中计算机图形学地发展,为我们提供了很多科学有效地算法,使得计算快速、准确、方便。
关键词:超市选址 链表 图形学 权值 邻接矩阵
第一章 绪 论
-
- 问题的提出
1.1.1 问题分析
对于某一学校超市,其他各单位到其的距离不同,同时各单位人员去超市的频度也不同。请为超市选址,要求实现总体代价最优。
说到求解一个地点,实现总体最优。就需要找到一个度量优、劣的标准。我们将各个单位到选址地的距离与该单位人员去超市频度的乘积作为单位的权数,再把各单位总权数相加所得的和作为该选址的一个优、劣度量标准。于是,权数和最小的为最优选址。
1.1.2 设计要求
(1)设计该问题的核心算法;
(2)设计程序能有效指出学校超市可设立的地点和各单位的位置以及它们之间的有效路径;
(3)程序能自动计算出最优设立点,并显示出最优设立点。
-
- 国内外研究的现状
不仅超市选址,其他诸多重要的设施在建立前都需要对其地点作出最优的抉择。该问题归根到底,就是要我们运用图的原理对其找到一个离各个单位综合最近的地点。随着数学方法,当今的数学的图的理论,已经较为完善,这位我们运用计算机解决该类问题提供了条件。
第二章 程序的主要功能
2.1 输入功能
输入学校的单位总数;
输入学校各单位的名称;
输入学校各单位人员去超市频度;
输入学校各单位间的距离(用无向图的邻接矩阵表示)
2.2 求权值的功能
求出将超市设在各个单位时,所得总的权值,返回用数组存储。
2.3 求最优功能
从上述的各个权值中,选出最小值为最优,并将最优值和对应的选址储存在链表中,返回头指针。
2.4 显示功能
显示最优地址的地点、总权数以及各单位到它的距离。
第三章 程序运行平台
Windows 操作系统
Visual C++
第四章 总体设计
第五章 模块分析
5.1 输入功能
1.定义一个整型变量,储存输入的单位数,为矩阵等输入确定阶;
2.定义一个二维的字符指针,用来存储输入的各个单位的名称,其中行数等于单位数。因为一个单位名称不超过20个字符,所以列数取定值20;
3.定义一个一维的浮点型指针,用来储存输入的各单位人员去超市的频度;
4.定义一个二维的浮点型指针,用来储存各单位间的距离,其中到自己的距离规定为0.
注:各个单位的名称、去超市频度以及它们间的距离输入顺序要一致。
5.2 求权值功能
对于每个单位来说,他们被选中时,所得权数就等于各个单位到它的距离乘以各个单位人员去超市频度的积,再分别相加便是总权数。
需要传入的参数是:指向单位间的距离矩阵的指针、指向单位人员去超市的频度的指针、单位数量。
需要返回的是:指向求得的权数的指针值。
5.3 求最优功能
在各个总权值中,最小的就是最优权值,我们将最优权值保留在第一个链表结点。由于输入是按统一的顺序,所以最优权值在数组中的位置对应的单位就是最优选址。我们把与最优值相等的权值在数组中的位置(即下标)保留在后续结点中。
5.4 显示功能
由于上述,最优权值在数组中的位置对应的单位就是最优选址,我们假设它在数组中的位置是i,那么单位名称数组中的第i个字符串就是最优选址的名称。距离矩阵中第i列元素是各个单位到选址超市的距离,距离矩阵中第i列各元素与频度数组中与该元素所在行的下标相同的值相乘就是相应单位到选址超市的权数。掌握这个规律,一一计算后输出便是需要的结果。
程序代码
#include<stdio.h>
#include<stdlib.h>
struct ZY //定义链表结构体,储存最优信息
{
double min;
int n;
ZY *next;
};
double*work_sum(float **A,float *B,int N)//求各单位被选中后的总权值
{
int n=N;
float **a=A;
float *b=B;
int i,j;
double s,*sum;
sum=(double *)malloc(n*sizeof(double));//分配内存空间
for(i=0;i<n;i++)
{
s=0.00;
for(j=0;j<n;j++) //求每个单位被选中后的权值
s=s+a[j][i]*b[j];
sum[i]=s;//储存每个单位被选中后的权值
}
return sum;//返回 sum
}
ZY *work_min(double *Sum,int N)//求最优选址
{
double *sum=Sum;
double min=sum[0];
int i;
int n=N;
ZY *head,*p;
head=(ZY *)malloc(sizeof(struct ZY));//分配内存空间
head->next=NULL;//尾指针置空
for(i=0;i<n;i++)
if(sum[i]<=min)
min=sum[i];
head->min=min;//求最优权值
for(i=0;i<n;i++)
if(sum[i]==min)
{
p=(ZY *)malloc(sizeof(struct ZY));
p->n=i;//记录最优选址点
p->next=head->next;
head->next=p;//尾指针置空
}
return head;
}
void print(ZY *Head,char **Dw,int N,float **A,float *B)//显示数据
{
ZY *head=Head;
ZY *p;
char **DW=Dw;
int i,k,n=N;
float **a=A;
float *b=B;
double min;
p=head->next;
min=head->min;
printf("最优选址如下:(总权重:%f)\n\n",min);
while(p)//显示最优选址信息
{
k=p->n;
printf("超市设立地点:%s\n",DW[k]);
for(i=0;i<n;i++)
printf("%s 到超市的有效路径为:%f 权重为:%f\n\n",DW[i],a[i][k],a[i][k]*b[i]);
p=p->next;
}
}
void input(int &n,float** &a,float* &b,char** &DW)//输入信息
{
int i,j;
printf("请输入单位数量:");
scanf("%d",&n);//输入单位数量
printf("\n");
a=(float **)malloc(n*sizeof(float*));//分配内存空间
for(i=0;i<n;i++)
a[i]=(float *)malloc(n*sizeof(float));//分配内存空间
b=(float *)malloc(n*sizeof(float));//分配内存空间
DW=(char **)malloc(n*sizeof(char *));//分配内存空间
for(i=0;i<n;i++)
DW[i]=(char *)malloc(20*sizeof(char));//分配内存空间
printf("请输入各单位的名称:\n");
for(i=0;i<n;i++)
scanf("%s",DW[i]);//输入各单位名称
printf("请输入各单位人员去超市的频度:\n");
for(i=0;i<n;i++)
scanf("%f",b+i);//输入各单位人员去超市频度
printf("请输入各单位间的距离矩阵:\n");
for(i=0;i<n;i++)//输入各单位间的距离矩阵
for(j=0;j<n;j++)
scanf("%f",a[i]+j);
}
int main()
{
float **a;
float *b;
double *sum;
int n;
ZY *head;
char **DW;
input(n,a,b,DW);
sum=work_sum(a,b,n);
head=work_min(sum,n);
print(head,DW,n,a,b);
}