NYOJ 7 街区最短路径问题

4 篇文章 0 订阅
看到这道题时自己推了会 并没有找到什么规律   在题解中出题人提示:  横纵坐标的中位数!    好吧 这道题第一个问题邮局位置就确定了,即将输入的x轴和y轴的数字排序取两者的中位数  两者的中位数就是邮局的位置 即到所有用户最短距离的位置   要问我为什么怎样  其实我自己也没搞太明白怎么找出的规律   不过在这先用着这个结论。解决了邮局位置的问题  接下来我们该解决怎么求出该位置到所有用户的距离是多少!这样就要用广搜了  广搜时需要用队列  我们需要队列存储遍历过得x(横坐标)和y(纵坐标);广搜时是从邮局位置开始搜索的的, 分别是四个方向搜索,如果该方向位置没有搜索过  就入队列!同时在搜索时记得矩阵有一个改变 就是该矩阵位置的值加一赋给他四周没被遍历过得位置(没有图也许这样说得不是太明白, 不过我在代码中注释好多,看过代码应该就知道说得什么意思了)等找到所有位置后  它本身矩阵位置的值就是邮局到该点的距离。把所有用户所处矩阵位置的值相加  就得到邮局到所有用户的最小距离之和!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int a[30], b[30],c[110][110], c1[110][110], e[30], f[30];
//a数组存的是横坐标 b数组存的是纵坐标 因为要对a和b数组排序  所以有添加两个数组e和f保存未排序时的a与b数组
//c数组是一个矩阵  c1数组是来记录该位置是否被访问过 
struct m{
	int l, k;
	int w;
}d[1500];//广搜时用到的队列  稍微开大点  我开始时开的有点小了 
int cmp(const void *a, const void *b)//快速排序用到的一个函数 
{
	return *(int *)a - *(int *)b;
}
void bfs(int x, int y, int m)//广搜函数 
{
	int front = 0, rear = 0, i, j, count = 0;
	d[rear].l = x; d[rear].k = y; d[rear].w = 1; rear++;
	if(c[x][y] == -10)
	{
		c[x][y] = 0;
		c1[x][y] = 1;
		count++;
	}//先判断由中位数得到的位置是不是已经有用户住,有的话计数器count加一 
	while(count != m)//当搜到所有的用户全部搜到时结束搜索 
	{
		if(d[front].l - 1 >= 0 && c1[d[front].l - 1][d[front].k] != 1)
		{
			if(c[d[front].l - 1][d[front].k] == -10) 
				count++;//如果该点是用户计数器加一 
			d[rear].l = d[front].l - 1; d[rear].k = d[front].k; d[rear].w = 1; rear ++;
			c[d[front].l - 1][d[front].k] = c[d[front].l][d[front].k] + 1;//本身加一的值赋给它四周未被遍历过的位置
			c1[d[front].l - 1][d[front].k] = 1;//当访问过就赋值为一	
		}
		if(d[front].l + 1 < 105 && c1[d[front].l + 1][d[front].k] != 1)
		{
			if(c[d[front].l + 1][d[front].k] == -10)
				count++;
			d[rear].l = d[front].l + 1; d[rear].k = d[front].k; d[rear].w = 1; rear++;
			c[d[front].l + 1][d[front].k] = c[d[front].l][d[front].k] + 1;//本身加一的值赋给它四周未被遍历过的位置
			c1[d[front].l + 1][d[front].k] = 1;
		}
		if(d[front].k - 1 >= 0 && c1[d[front].l][d[front].k - 1] != 1)
		{
			if(c[d[front].l][d[front].k - 1] == -10)
				count++;
			d[rear].l = d[front].l; d[rear].k = d[front].k - 1; d[rear].w = 1; rear++;
			c[d[front].l][d[front].k - 1] = c[d[front].l][d[front].k] + 1;//本身加一的值赋给它四周未被遍历过的位置
			c1[d[front].l][d[front].k - 1] = 1;	
		}
		if(d[front].k + 1 < 105 && c1[d[front].l][d[front].k + 1] != 1)
		{
			if(c[d[front].l][d[front].k + 1] == -10)
				count++;
			d[rear].l = d[front].l; d[rear].k = d[front].k + 1; d[rear].w = 1; rear++;//本身加一的值赋给它四周未被遍历过的位置
			c[d[front].l][d[front].k + 1] = c[d[front].l][d[front].k] + 1;
			c1[d[front].l][d[front].k + 1] = 1;	
		}
		front++;
	}
	
}
int f1(int m, int *e)//这个函数就是把用户所处矩阵各个位置相加
{
	int sum = 0, i;
	for(i = 0; i < m; i++)
	{
		sum += c[e[i]][f[i]];
	}
	return sum;
}
int main()
{
	int t, m, i, x, y, temp1, temp2, sum;
	//int e[30], e1[30];
	scanf("%d", &t);
	while(t--)
	{
		for( i = 0; i < 105; i++ )
			d[i].w = 0;
		memset(c, 0, sizeof(c));
		memset(c1, 0, sizeof(c1));//把矩阵初始为零值
		scanf("%d", &m);
		for(i = 0; i < m; i++)
		{
			scanf("%d%d", &x, &y);
			a[i] = e[i] = x;
			b[i] = f[i] = y;
			c[x][y] = -10;//有用户的位置被赋值为-10
		}
		qsort(a, m, sizeof(int), cmp);//快速排序 
		qsort(b, m, sizeof(int), cmp);
		if(m % 2)
		{
			temp1 = a[m / 2];
			temp2 = b[m / 2];
			bfs(temp1, temp2, m);
			sum = f1(m, e);
			printf("%d\n", sum);
		}
		else
		{
			temp1 = (a[m / 2] + a[m / 2 - 1]) / 2;
			temp2 = (b[m / 2] + b[m / 2 - 1]) / 2;
			bfs(temp1, temp2, m);
			sum = f1(m, e);
			printf("%d\n", sum);
		}
	}
	return 0;
}
好吧,我自己感觉自己解释的就不清晰   大家人为应该怎么写题解更好 可以给我下建议  下回我会注意!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值