超市选址问题

问题:在一个按照东西和南北方向划分成规整街区的城市里,n个居民点散乱地分布在不同的街区中。用x坐标表示东西向,用y坐标表示南北向。各居民点的位置可以由坐标(x,y)表示。街区中任意两点(x1,y1)和(x2,y2)之间的距离可以用数值|x1-x2|+|y1-y2|度量。居民们希望在城市中选择建立超市的最佳位置,使n个居民点到超市的距离总和最小。
编程任务:给定n个居民点的位置,编程计算n个居民点到超市的距离总和的最小值。

输入:输入由多组测试数据组成。每组测试数据输入的第1行是居民点数n,接下来n行是居民点的位置,每行两个整数x和y。

输出:对应每组输入,输出数据是n个居民点到超市距离总和的最小值。
输入示例: 5 居民点到超市最小距离和:10
1 2
2 2
1 3
3 -2
3 3
解决方法:超市选址问题的核心可以看成是求中值的问题,即n个居民点的横、纵坐标值的中位数就是最优解。为此可先求出n个居民点的x坐标值和y坐标值的中位数,然后由此求得n个居民点到超市距离总和的最小值。

注意事项:本实验需完成算法设计、数据结构的选择、运行结果分析以及相关内容的说明等。例如,求中位数的过程可用快速排序等算法将n个居民点的x和y坐标分别排序后,计算出中位数。程序的编写可以参考以下步骤:
1、输入居民点位置文件,或用随机数发生器得到各居民点位置坐标(x,y)。
2、将输入的二维数组(x,y)转化为两个一维数组(x)、(y)。
3、计算横坐标和纵坐标数组的中位数。
4、求n个居民点到超市距离总和的最小值,并输出此值,并以图示的方式显示居民点与超市的位置分布。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void sort(int *a,int len)
{int i=0;
 int j;
 int t;
    for(i=0;i<len;i++)
    {
        for(j=0;j<len-i-1;j++)
        {
            if(a[j]>a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
        }
    }
} 

int Median(int *x,int n){//返回数组中的中位数
	if(n%2==0){
		return ((x[n/2-1]+x[n/2])/2);
	}
	else {
		return (x[n/2]);
	}
}//Median

int main(){
	int n;//居民点个数n
	int map[12][12];
	int *x;
	int *y;
	int i=0,j=0;
	for(i=0;i<12;i++){//map初始化
		for(j=0;j<12;j++){
			map[i][j]=0;
		}
	}//for   0为空,1为坐标原点,2为超市位置,3为居民点,4为原点与超市重合,5为超市与居民区重合,6为居民区与原点重合
	map[5][5]=1;//该点为坐标原点
	printf("The number of people:\n");
	scanf("%d",&n);
	x=(int*)malloc(sizeof(int)*n);
	y=(int*)malloc(sizeof(int)*n);
	printf("The number of x and y\n");
	for(i=0;i<n;i++){
		scanf("%d",&x[i]);
		scanf("%d",&y[i]);
		if(map[x[i]-1+6][y[i]-1+6]==0){
			map[x[i]-1+6][y[i]-1+6]=3;
		}
		else if(map[x[i]-1+6][y[i]-1+6]==1){
			map[x[i]-1+6][y[i]-1+6]=6;
		}
	}//for
	//冒泡法
	sort(x,n);
	sort(y,n);
	//求中位数
	int Med_x=0,Med_y=0;
	int juli=0;
	Med_x=Median(x,n);
	Med_y=Median(y,n);
	if(map[Med_x-1+6][Med_y-1+6]==0){
		map[Med_x-1+6][Med_y-1+6]=2;
	}
	else if(map[Med_x-1+6][Med_y-1+6]==1){
		map[Med_x-1+6][Med_y-1+6]=4;
	}
	else if(map[Med_x-1+6][Med_y-1+6]==3){
		map[Med_x-1+6][Med_y-1+6]=5;
	}
	

	for(i=0;i<n;i++){
		juli=juli+abs(Med_x-x[i]);
	}
	for(i=0;i<n;i++){
		juli=juli+abs(Med_y-y[i]);
	}
	printf("%d\n",juli);

	for(j=11;j>=0;j--){
		for(i=0;i<12;i++){
			if(map[i][j]==0){
				printf(" ^ ");
			}//if0
			else if(map[i][j]==1){
				printf(" 0 ");
			}//if1
			else if(map[i][j]==2){
				printf(" S ");
			}//if2
			else if(map[i][j]==3){
				printf(" P ");
			}//if3
			else if(map[i][j]==4){
				printf(" h ");
			}//if1
			else if(map[i][j]==5){
				printf(" y ");
			}//if1
			else if(map[i][j]==6){
				printf(" m ");
			}//if1
		}//for2
		printf("\n");
	}//for1

	return 0;
}//main

实验结果:
实验输入实验输入
实验输出:
实验输出

  • 14
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哦,这是一个有趣的问题,需要考虑许多因素来确定最佳的选址。我们可以使用C语言编写一个程序,来解决这个问题。下面是一个可能的解决方案: 首先,我们需要定义一些变量,包括:学校位置,超市位置,超市数量,以及超市名称等等。例如: ``` int school_x, school_y; // 学校位置 int market_x[MAX_MARKET], market_y[MAX_MARKET]; // 超市位置 int num_market; // 超市数量 char market_name[MAX_MARKET][MAX_NAME_LEN]; // 超市名称 ``` 然后,我们需要编写一个函数来计算学校和超市之间的距离。这可以使用勾股定理来计算: ``` double distance(int x1, int y1, int x2, int y2) { return sqrt(pow(x1-x2, 2) + pow(y1-y2, 2)); } ``` 接下来,我们需要编写一个函数来计算每个超市到学校的距离,并选择最短的距离。这可以使用一个循环来实现: ``` int find_best_market() { double best_distance = INFINITY; int best_market = -1; for (int i = 0; i < num_market; i++) { double d = distance(school_x, school_y, market_x[i], market_y[i]); if (d < best_distance) { best_distance = d; best_market = i; } } return best_market; } ``` 最后,我们可以在主函数中调用这些函数,并输出结果: ``` int main() { // 输入学校位置,超市数量,超市名称和位置等信息 // ... // 找到最佳超市 int best_market = find_best_market(); // 输出结果 printf("最佳超市是%s,距离学校%.2lf米。\n", market_name[best_market], distance(school_x, school_y, market_x[best_market], market_y[best_market])); return 0; } ``` 当然,这只是一个简单的示例程序,实际情况可能更加复杂。例如,我们可能需要考虑超市的规模、竞争对手、租金等因素来确定最佳的选址。但是,这个程序可以作为一个基础框架,帮助我们开始解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值