【回溯】B055_LQ_邮局(暴搜 / dp?)

一、Problem

C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。

现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。

输入格式

输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。

接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。

接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。

在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。

输出格式

输出一行,包含k个整数,从小到大依次表示你选择的备选邮局编号。(备选邮局按输入顺序由1到m编号)

样例输入
5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2
样例输出
2 4

数据规模和约定

对于 30 % 30\% 的数据, 1 < = n < = 10 1 < = m < = 10 1 < = k < = 5 1<=n<=10,1<=m<=10,1<=k<=5
对于 60 % 60\% 的数据, 1 < = m < = 20 1<=m<=20
对于 100 % 100\% 的数据, 1 < = n < = 50 1 < = m < = 25 1 < = k < = 10 1<=n<=50,1<=m<=25,1<=k<=10

扫描二维码关注公众号,回复: 11168073 查看本文章

二、Solution

题意:从 m 个邮局中选 k 个,使得每户村民到这 k 个邮局中距离最近的邮局的距离总和最小…

方法一:dfs + 枚举(超时)

  • 定义 Pos 类存储村民和邮局的坐标…
  • dfs 从 m 个邮局选取 k 后,立即判断每户村民到这 k 个邮局的距离总和…
  • 取其中可构成每户村民距离总和最小的 k 个邮局的编号…

40/100

可以优化一下:预处理一下每个村民到最近的邮局的距离到数组中…

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		int N, M, K;
		int INF = 0x3f3f3f3f, MIN;
		Pos[] hm;
		Pos[] stp;
		int[] res, tmp;
		
		int mini(int id) {
			int min = INF;
			for (int i = 0; i < K; i++) {
				int sID = tmp[i];
				int a = hm[id].x-stp[sID].x;
				int b = hm[id].y-stp[sID].y;
				min = Math.min(min, (int)Math.sqrt(a*a + b*b));
			}
			return min;
		}
		void dfs(int c) {
			if (c == K) {
				int sum = 0;
				for (int i = 0; i < N; i++)
					sum += mini(i);
				if (sum < MIN) {
				    MIN = sum;
    				res = Arrays.copyOf(tmp, tmp.length-1);
				}
				return;
			}
			for (int i = c; i < M; i++) {
				tmp[c] = i;
				dfs(c+1);
			}
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			N = sc.nextInt();
			M = sc.nextInt();
			K = sc.nextInt();
			hm = new Pos[N];
			stp = new Pos[N];
			
			for (int i = 0; i < N; i++) {
				int a = sc.nextInt(), b = sc.nextInt();
				hm[i] = new Pos(a, b);
			}
			for (int i = 0; i < M; i++) {
				int a = sc.nextInt(), b = sc.nextInt();
				stp[i] = new Pos(a, b);
			}
			res = new int[K+5];
			tmp = new int[K+5];
			MIN = INF;
			dfs(0);
			System.out.print(res[0]+1);
			for (int i = 1; i < K; i++)
				System.out.printf(" %d",res[i]+1);
		}
		class Pos {
			int x, y;
			Pos(int x, int y) {this.x = x;this.y = y;}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

复杂度分析

  • 时间复杂度: O ( 2 m ) O(2^m)
  • 空间复杂度: O ( . . . ) O(...)

方法二:dp

代办…

复杂度分析

  • 时间复杂度: O ( ) O()
  • 空间复杂度: O ( ) O()
原创文章 787 获赞 314 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/105863620
DP
DP?