2014年第五届蓝桥杯Java程序设计本科B组决赛个人题解汇总:
https://blog.csdn.net/daixinliangwyx/article/details/89948727
第六题
标题:供水设施
交题测试链接:https://www.dotcpp.com/oj/problem1817.html
X星球的居民点很多。Pear决定修建一个浩大的水利工程,以解决他管辖的N个居民点的供水问题。现在一共有N个水塔,同时也有N个居民点,居民点在北侧从1号到N号自西向东排成一排;水塔在南侧也从1号到N号自西向东排成一排。
N条单向输水线(有水泵动力),将水从南侧的水塔引到北侧对应的居民点。
我们不妨将居民点和水塔都看做平面上的点,居民点坐标为(1,K)~(N,K),水塔为(1,0)~(N,0)。
除了N条纵向输水线以外,还有M条单向的横向输水线,连接(Xi,Yi)和(Xi,(Yi)+1)或者(Xi,Yi)和(Xi,(Yi)-1)。前者被称为向右的水路,而后者是向左的。不会有两条水路重叠,即便它们方向不同。
布局的示意图如:【p1.png】所示。
显然,每个水塔的水都可以到达若干个居民点(而不仅仅是对应的那个)。例如上图中,4号水塔可以到达3、4、5、6四个居民点。
现在Pear决定在此基础上,再修建一条横向单项输水线。为了方便考虑,Pear认为这条水路应当是自左向右的,也就是连接了一个点和它右侧的点(例如上图中连接5和6两个纵线的横向水路)。
Pear的目标是,修建了这条水路之后,能有尽可能多对水塔和居民点之间能到达。换句话说,设修建之后第i个水塔能到达Ai个点,你要最大化A1+A2+...+An。
根据定义,这条路必须和X轴平行,但Y坐标不一定要是整数。注意:虽然输入中没有重叠的水路,但是你的方案可以将新修的输水线路与已有的水路重叠。
【输入数据】
输入第一行包含三个正整数N,M,K,含义如题面所述:N是纵向线数,M横向线数,K是居民点纵坐标。
接下来M行,每行三个整数。前两个正整数Xi Yi表示水路的起点坐标;
1<=Xi<=N,0<Yi<K。
接下来一个数0或者1,如果是0表示这条水路向左,否则向右。
保证水路都是合法的,也就是不会流向没有定义的地方。
【输出数据】
输出一行。是一个正整数,即:题目中要求的最大化的A1+A2+...+An。
【输入样例1】
4 3 2
1 1 1
3 1 0
3 1 1
【输出样例1】
11
【输入样例2】
7 9 4
2 3 0
7 2 0
6 3 1
6 1 0
2 1 1
3 3 1
5 2 0
2 2 1
7 1 0
【输出样例2】
21
【数据范围】
对于20%的数据,N,K<=20,M<=100
对于40%的数据,N,K<=100,M<=1000
对于60%的数据,N,K<=1000,M<=100000
对于100%的数据,N,K<=50000,M<=100000
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
不会满分的解法,只能用暴力模拟得了25分(满分100分),暴力就是用两个set数组:一个set用来存当前水塔可以到达的居民点;另一个set用来存当前水塔的前驱水塔(可能有多个),这个前驱set用来将最新能到的居民点递归加到所有前驱水塔的到达set里。然后处理完给出的原始数据后,遍历模拟添加新的水路,不断更新全部水塔能够到达居民点数量之和的最大值。
25分代码:
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class Main4 {
public static InputReader in = new InputReader(new BufferedInputStream(System.in));
public static PrintWriter out = new PrintWriter(System.out);
public static int n, m, k, x, y, dir, sum, maxadd, nowadd, sumadd;
public static int[] num = new int[50010];
public static int[] vis;
public static HashSet<Integer>[] to = new HashSet[50010];
public static HashSet<Integer>[] tmpto = new HashSet[50010];
public static HashSet<Integer>[] pre = new HashSet[50010];
public static void main(String[] args) {
n = in.nextInt();
m = in.nextInt();
k = in.nextInt();
for (int i = 1; i <= n; i++) {
num[i] = 1;
to[i] = new HashSet<>();
to[i].add(i);
pre[i] = new HashSet<>();
tmpto[i] = new HashSet<>();
}
for (int i = 0; i < m; i++) {
x = in.nextInt();
y = in.nextInt();
dir = in.nextInt();
if (y <= k) {
if (dir == 1) {
to[x].addAll(to[x+1]);
pre[x+1].add(x);
vis = new int[50010];
vis[x] = 1;
vis[x+1] = 1;
add(x, x+1);
} else {
to[x].addAll(to[x-1]);
pre[x-1].add(x);
vis = new int[50010];
vis[x] = 1;
vis[x-1] = 1;
add(x, x-1);
}
}
}
sum = 0;
for (int i = 1; i <= n; i++)
sum += to[i].size();
for (int i = 1; i <= n; i++) {
if (i < n) {//可以向右
for (int j = 1; j <= n; j++) {
tmpto[j].clear();
tmpto[j].addAll(to[j]);
}
tmpto[i].addAll(tmpto[i+1]);
vis = new int[50010];
vis[i] = 1;
vis[i+1] = 1;
testadd(i, i+1);
sumadd = 0;
for (int j = 1; j <= n; j++)
sumadd += tmpto[j].size();
sum = Math.max(sum, sumadd);
}
if (i > 1) {//可以向左
for (int j = 1; j <= n; j++) {
tmpto[j].clear();
tmpto[j].addAll(to[j]);
}
tmpto[i].addAll(tmpto[i-1]);
vis = new int[50010];
vis[i] = 1;
vis[i-1] = 1;
testadd(i, i-1);
sumadd = 0;
for (int j = 1; j <= n; j++)
sumadd += tmpto[j].size();
sum = Math.max(sum, sumadd);
}
}
out.println(sum);
out.flush();
out.close();
}
static void testadd(int x, int join) {
int len = pre[x].size();
if (len == 0) return;
for (Integer f : pre[x]) {
if (vis[f] == 0) {
vis[f] = 1;
tmpto[f].addAll(tmpto[join]);
testadd(f, join);
}
}
}
static void add(int x, int join) {
int len = pre[x].size();
if (len == 0) return;
for (Integer f : pre[x]) {
if (vis[f] == 0) {
vis[f] = 1;
to[f].addAll(to[join]);
add(f, join);
}
}
}
static class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
public BigDecimal nextBigDecimal() {
return new BigDecimal(next());
}
}
}