NYOJ 7 街区最短路径问题
2013-12-04 00:59
483 查看
看到这道题时自己推了会 并没有找到什么规律 在题解中出题人提示: 横纵坐标的中位数! 好吧 这道题第一个问题邮局位置就确定了,即将输入的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; }
好吧,我自己感觉自己解释的就不清晰 大家人为应该怎么写题解更好 可以给我下建议 下回我会注意!
相关文章推荐
- NYOJ 7 街区最短路径问题
- nyoj 7 街区最短路径问题
- NYOJ 7 街区最短路径问题
- NYOJ-7:街区最短路径问题
- NYOJ 7-街区最短路径问题(曼哈顿距离)
- NYOJ:7-街区最短路径问题
- NYOJ-7-街区最短路径问题
- NYOJ 7(街区最短路径问题)
- nyoj7街区最短路径问题
- NYOJ——7 街区最短路径问题
- nyoj7街区最短路径问题
- nyoj-7-街区最短路径问题
- nyoj 7:街区最短路径问题
- nyoj 7 街区最短路径问题 暴力枚举
- nyoj 7 街区最短路径问题 【数学】
- NYoj-街区最短路径问题
- NYOJ 7 街区最短路径问题
- NYOJ-----7---街区最短路径问题
- NYOJ 街区最短路径问题
- nyoj 7 街区最短路径问题