@ 蓝桥杯 练习系统 历届试题 PREV-24
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
C村住着n户村民,由于交通闭塞,C村的村民只能通过信件与外界交流。为了方便村民们发信,C村打算在C村建设k个邮局,这样每户村民可以去离自己家最近的邮局发信。
现在给出了m个备选的邮局,请从中选出k个来,使得村民到自己家最近的邮局的距离和最小。其中两点之间的距离定义为两点之间的直线距离。
输入格式
输入的第一行包含三个整数n, m, k,分别表示村民的户数、备选的邮局数和要建的邮局数。
接下来n行,每行两个整数x, y,依次表示每户村民家的坐标。
接下来m行,每行包含两个整数x, y,依次表示每个备选邮局的坐标。
在输入中,村民和村民、村民和邮局、邮局和邮局的坐标可能相同,但你应把它们看成不同的村民或邮局。
输出格式
输出一行,包含k个整数,从小到大依次表示你选择的备选邮局编号。(备选邮局按输入顺序由1到m编号)
测试样例1
Input:
5 4 2
0 0
2 0
3 1
3 3
1 1
0 1
1 0
2 1
3 2
Output:
2 4
数据规模与约定
对于30%的数据,1<=n<=10,1<=m<=10,1<=k<=5;
对于60%的数据,1<=m<=20;
对于100%的数据,1<=n<=50,1<=m<=25,1<=k<=10。
ACcode:
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int n, m, k, selected[];
static float min, table[][];
static Node[] home;
public static void main(String[] args) {
InputReader in = new InputReader(System.in, " ");
n = in.nextInt(); m = in.nextInt(); k = in.nextInt();
min = Float.MAX_VALUE;
table = new float[m][n];
selected = new int[k];
home = new Node[n];
for (int i = 0; i < n; i++)
home[i] = new Node(in.nextInt(), in.nextInt());
for (int k = 0, x, y; k < m; k++) {
x = in.nextInt();
y = in.nextInt();
for (int i = 0; i < n; i++)
table[k][i] = (float)Math.sqrt(squa(home[i].x - x) + squa(home[i].y - y));
}
float[] sum = new float[n];
Arrays.fill(sum, Float.MAX_VALUE);
LinkedList<Integer> select = new LinkedList();
dfs(0, 0, sum, select);
for (int i = 0; i < k; i++) System.out.print(selected[i] + " ");
}
static Set<Integer> set = new HashSet();
static void dfs(int cnt, int cur, float[] sum, LinkedList<Integer> select) {
if (n - cur + cnt < k) return;
if (cnt == k) {
float s = 0;
for (int i = 0; i < n; i++) s += sum[i];
if (s < min) {
min = s;
Iterator<Integer> se = select.iterator();
for (int i = 0; i < k; i++)
selected[i] = se.next() + 1;
}
} else if (cur < m){
float[] tmp = new float[n];
System.arraycopy(sum, 0, tmp, 0, n);
dfs(cnt, cur + 1, sum, select);
if (set.contains(cur)) return;
boolean flag = false;
for (int i = 0; i < n; i++)
if (table[cur][i] < tmp[i]) {
flag = true;
tmp[i] = table[cur][i];
}
if (flag) {
select.add(cur);
dfs(cnt + 1, cur + 1, tmp, select);
select.removeLast();
} else set.add(cur);
}
}
static int squa(int x) {
return x * x; }
static class Node {
int x, y;
Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static class InputReader {
BufferedReader read;
StringTokenizer tok;
String delimiters;
InputReader(InputStream in) {
this(in, " \n\t\r\f"); }
InputReader(InputStream in, String delimiters) {
this.read = new BufferedReader(new InputStreamReader(in));
this.tok = new StringTokenizer("", this.delimiters = delimiters);
}
String next() {
while (!tok.hasMoreTokens())
try {
tok = new StringTokenizer(read.readLine(), delimiters);
} catch (IOException e) {
}
return tok.nextToken();
}
int nextInt() {
return Integer.parseInt(next()); }
}
}
倒也不是多复杂的题,但不修剪一下节点内存会超限
遇事不决先枚举
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int n, m, k, selected[];
static double min, table[][];
static Node[] home;
public static void main(String[] args) {
InputReader in = new InputReader(System.in, " ");
n = in.nextInt(); m = in.nextInt(); k = in.nextInt();
min = Double.MAX_VALUE;
table = new double[m][n];
selected = new int[k];
home = new Node[n];
for (int i = 0; i < n; i++)
home[i] = new Node(in.nextInt(), in.nextInt());
for (int k = 0, x, y; k < m; k++) {
x = in.nextInt();
y = in.nextInt();
for (int i = 0; i < n; i++)
table[k][i] = Math.sqrt(squa(home[i].x - x) + squa(home[i].y - y));
}
double[] sum = new double[n];
Arrays.fill(sum, Double.MAX_VALUE);
LinkedList<Integer> select = new LinkedList();
dfs(0, 0, sum, select);
for (int i = 0; i < k; i++) System.out.print(selected[i] + " ");
}
static void dfs(int cnt, int cur, double[] sum, LinkedList<Integer> select) {
if (cnt == k) {
double s = 0;
for (int i = 0; i < n; i++) s += sum[i];
if (s < min) {
min = s;
Iterator<Integer> se = select.iterator();
for (int i = 0; i < k; i++)
selected[i] = se.next() + 1;
}
} else if (cur < m){
double[] tmp = new double[n];
System.arraycopy(sum, 0, tmp, 0, n);
for (int i = 0; i < n; i++)
if (table[cur][i] < tmp[i]) tmp[i] = table[cur][i];
select.add(cur);
dfs(cnt + 1, cur + 1, tmp, select);
select.removeLast();
dfs(cnt, cur + 1, sum, select);
}
}
static int squa(int x) {
return x * x; }
static class Node {
int x, y;
Node(int x, int y) {
this.x = x;
this.y = y;
}
}
static class InputReader {
BufferedReader read;
StringTokenizer tok;
String delimiters;
InputReader(InputStream in) {
this(in, " \n\t\r\f"); }
InputReader(InputStream in, String delimiters) {
this.read = new BufferedReader(new InputStreamReader(in));
this.tok = new StringTokenizer("", this.delimiters = delimiters);
}
String next() {
while (!tok.hasMoreTokens())
try {
tok = new StringTokenizer(read.readLine(), delimiters);
} catch (IOException e) {
}
return tok.nextToken();
}
int nextInt() {
return Integer.parseInt(next()); }
}
}
434mb 和 256mb 差的属实有点多
不过该题并没有要求精度输出距离合,改用 float试试
还差点意思
static void dfs(int cnt, int cur, float[] sum, LinkedList<Integer> select) {
if (n - cur + cnt < k) return;
if (cnt == k) {
float s = 0;
for (int i = 0; i < n; i++) s += sum[i];
if (s < min) {
min = s;
Iterator<Integer> se = select.iterator();
for (int i = 0; i < k; i++)
selected[i] = se.next() + 1;
}
} else if (cur < m){
float[] tmp = new float[n];
boolean flag = false;
System.arraycopy(sum, 0, tmp, 0, n);
for (int i = 0; i < n; i++)
if (table[cur][i] < tmp[i]) {
flag = true;
tmp[i] = table[cur][i];
}
if (flag) {
select.add(cur);
dfs(cnt + 1, cur + 1, tmp, select);
select.removeLast();
}
dfs(cnt, cur + 1, sum, select);
}
}
我就纳闷了,不能给点反馈?