CCF計算機職業資格認證考試練習——20180902買菜(Java實現)

問題描述

  小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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章