问题描述
小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁边的一个广场把菜装上车,两人都要买n种菜,所以也都要装n次车。具体的,对于小H来说有n个不相交的时间段[a1,b1],[a2,b2]...[an,bn]在装车,对于小W来说有n个不相交的时间段[c1,d1],[c2,d2]...[cn,dn]在装车。其中,一个时间段[s, t]表示的是从时刻s到时刻t这段时间,时长为t-s。
由于他们是好朋友,他们都在广场上装车的时候会聊天,他们想知道他们可以聊多长时间。
输入格式
输入的第一行包含一个正整数n,表示时间段的数量。
接下来n行每行两个数ai,bi,描述小H的各个装车的时间段。
接下来n行每行两个数ci,di,描述小W的各个装车的时间段。
输出格式
输出一行,一个正整数,表示两人可以聊多长时间。
样例输入
4
1 3
5 6
9 13
14 15
2 4
5 7
10 11
13 14
样例输出
3
数据规模和约定
对于所有的评测用例,1 ≤ n ≤ 2000, ai < bi < ai+1,ci < di < ci+1,对于所有的i(1 ≤ i ≤ n)有,1 ≤ ai, bi, ci, di ≤ 1000000。
解题思路
思考之后觉得,解决这个问题应该就是把问题拆成几种情况,对每个时间段分情况讨论。
一开始觉得只有下面两种情况是可以增加聊天时间的,其余都不行:
1、小H的起始点位于小W的时间段中间(判断条件左闭右开)
(1)小H的结束点位于小W的时间段中间
(2)小H的结束点位于小W的结束点右边
2、小W的起始点位于小H的时间段中间(判断条件左闭右开)
(1)小W的结束点位于小H的时间段中间
(2)小W的结束点位于小H的结束点右边
于是分情况讨论出了下面的代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int time = 0;
int[][] H = new int[n][2];
int[][] W = new int[n][2];
for(int i=0;i<n;i++) {
H[i][0] = sc.nextInt();
H[i][1] = sc.nextInt();
}
for(int i=0;i<n;i++) {
W[i][0] = sc.nextInt();
W[i][1] = sc.nextInt();
}
for(int i=0;i<n;i++) {
if(H[i][0]>=W[i][0] && H[i][0]<W[i][1]) {
if(H[i][1]<W[i][1]) {
time += H[i][1]-H[i][0];
}
else {
time += W[i][1]-H[i][0];
}
}
else if(W[i][0]>=H[i][0] && W[i][0]<W[i][1]) {
if(W[i][1]<H[i][1]) {
time += W[i][1]-W[i][0];
}
else {
time += H[i][1]-W[i][0];
}
}
else {
break;
}
}
System.out.println(time);
}
}
在eclipse中自己测试了一下,使用了题中所给的输入样例,发现可以正确输出,然后兴高采烈地放到了网页上检测,结果显示错误!
思前想后搞不懂为什么会错误,明明输入和输出都跟样例一样了呀!
后来又是借鉴了一篇博客,才想明白自己到底哪里出错了:解决问题时根本没有把所有地情况全部考虑到!
举个例子:如果小H某次时间跨度是 [9,14] ,而小W某两次时间跨度是 [10,11] 和 [13,14] ,那么小H就可以包含两次小W的时间跨度!然而在上面的代码中并不能做到这一点,上面的代码会这么运行:[9,14] 和 [10,11] 进行比较,发现覆盖了 [10,11] ,然后就会进入下一个循环,计算 [15,16] 和 [13,14] 之间的关系,结果没有重复,就不会记录 [13,14] 这次的聊天时间!
发现问题之后就很好办了,改变思路,多进行一次for循环就可以了。代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int time = 0;
int[][] H = new int[n][2];
int[][] W = new int[n][2];
for(int i=0;i<n;i++) {
H[i][0] = sc.nextInt();
H[i][1] = sc.nextInt();
}
for(int i=0;i<n;i++) {
W[i][0] = sc.nextInt();
W[i][1] = sc.nextInt();
}
for(int h=0;h<n;h++) {
for(int w=0;w<n;w++) {
if(H[h][0]<=W[w][0]) {
if(H[h][1]>W[w][0]&&H[h][1]<=W[w][1]) {
time += H[h][1]-W[w][0];
}
else if(H[h][1]>W[w][1]) {
time += W[w][1]-W[w][0];
}
}
else if(H[h][0]>W[w][0]&&H[h][0]<W[w][1]) {
if(H[h][1]<=W[w][1]) {
time += H[h][1]-H[h][0];
}
else if(H[h][1]>W[w][1]) {
time += W[w][1]-H[h][0];
}
}
}
}
System.out.println(time);
}
}
运行。正确。时间使用:406ms,空间使用31.25MB
在网上还看到了一篇博客,其中将正确代码进行了优化,提前终止了不必要的循环。
附上链接:https://blog.csdn.net/qq_29110265/article/details/83511790