首页 > 试题广场 >

安排超市

[编程题]安排超市
  • 热度指数:857 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个n*n的地图。地图是上下左右四联通的,不能斜向行走:
*代表障碍,不可通行。
.代表路,可以通行。
#代表房子。房子也是可以通行的。

小红现在需要在一些地方安排一些超市(不能安排在障碍物上,可以安排在路上或者房子上。超市也是可以通行的)。
小红希望每个房子至少可以到达一个超市。同时由于成本原因,小红希望超市的数量尽可能少。
在超市数量最少的情况下,小红希望每个房子到达最近的超市的距离之和尽可能小。
她想知道超市最少的数量,以及最小的距离之和。你能帮帮她吗?

输入描述:
第一行一个正整数n,代表地图的大小。( 1<=n<=50 )
接下来的n行,每行一个长度为n的字符串,表示整个地图。保证输入合法。


输出描述:
输出两个整数,用空格隔开。分别代表超市的最小数量、最小的距离之和。
示例1

输入

3
#.#
.**
*.#

输出

2 2

说明

下标从1开始,第一个超市安排的位置是(1,2),第二个超市安排的位置是(3,3)。三个房子到超市的距离分别为1,1,0。 
示例2

输入

3
#*#
.**
*.#

输出

3 0

说明

分别在三个房子上建3个超市即可。 
示例3

输入

2
.*
*.

输出

0 0

说明

没有房子,所以不用造超市 

分析

首先需要计算商店最少个数,每一个房子都可以前往商店购物,即'*'将地图分成了n份,那么就是n个商店(深度优先算法)
然后计算每个区域内的房子到达商店的距离和最小,也就保证了总体最小(广度优先算法)。

代码

import java.util.*;
/**
 * @author xuan
 * @date 2022/4/15 12:47
 */
public class No4 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();
        char[][] map = new char[n][n];
        char[][] map1 = new char[n][n];
        int[][] H = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        int ans1 = 0;
        int ans2 = 0;
        for (int i = 0; i < n; i++) {
            map[i] = sc.nextLine().trim().toCharArray();
            map1[i] = map[i].clone();
        }
        //对每个节点进行深度优先递归统计区域个数,并且统计区域内包含的节点
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                //节点为房子需要递归。可能一个区域内没有'#',那么不需要递归
                if (map1[i][j] == '#') {
                    ans1++; //区域个数也就是商店数量
                    List list = new ArrayList();//统计本区域内的所有节点
                    dfs(map1, i, j, list);//深度优先递归将这个区域内的节点全部遍历
                    int min = Integer.MAX_VALUE;
                    //将商店设置在coordinate,统计此区域内最小距离和
                    for (int[] coordinate : list) {
                        int min1 = 0;
                        int step = 0; //商店到节点的距离
                        //广度优先
                        boolean[][] flag = new boolean[n][n];
                        Queue queue = new LinkedList();
                        queue.offer(coordinate);
                        flag[coordinate[0]][coordinate[1]] = true;
                        while (!queue.isEmpty()) {
                            int size = queue.size();
                            for (int k = 0; k < size; k++) {
                                int[] poll = queue.poll();
                                int x = poll[0], y = poll[1];
                                //如果此节点是房子,那么需要统计距离
                                if (map[x][y] == '#') {
                                    min1 += step;
                                }
                                for (int l = 0; l < 4; l++) {
                                    int xx = x + H[l][0];
                                    int yy = y + H[l][1];
                                    //超过边界或者不是此区域或者遍历过 则不加入队列
                                    if (xx = n || yy >= n || map[xx][yy] == '*' || flag[xx][yy]) {
                                        continue;
                                    }
                                    queue.offer(new int[]{xx, yy});
                                    //标记已遍历
                                    flag[xx][yy] = true;
                                }
                            }
                            step++;
                        }
                        //求出此区域内的最小距离和
                        min = Math.min(min1, min);
                    }
                    //总的距离和
                    ans2 += min;
                }
            }
        }
        System.out.println(ans1 + " " + ans2);
    }
    /**
     * 
     * @param map 备份的地图
     * @param x 纵坐标
     * @param y 横坐标
     * @param list 统计此区域内的节点
     */
    public static void dfs(char[][] map, int x, int y, List list) {
        int n = map.length;
        if (x = n || y >= n || map[x][y] == '*') {
            return;
        }
        list.add(new int[]{x, y});
        //标记已遍历
        map[x][y] = '*';
        //遍历上下左右
        dfs(map, x - 1, y, list);
        dfs(map, x + 1, y, list);
        dfs(map, x, y - 1, list);
        dfs(map, x, y + 1, list);
    }
}
编辑于 2022-04-15 16:32:02 回复(0)

问题信息

上传者:小小
难度:
1条回答 2708浏览

热门推荐

通过挑战的用户

安排超市