杭電OJ 1006題 題目連結:點擊開啟連結
本題思路:最開始嘗試使用枚舉的方法,以s為單位進行遍曆時發現結果的精度不夠,以ms為單位時可以滿足精度要求,但是會逾時。最終解題思路如下:
(1)秒針1s走6度,分針1s走0.1度,時針1s走1/120度。所以分針秒針每秒的度數差為5.9°,時針分針每秒的度數差為11/120°,時針秒針每秒的度數差為719/120°。
(2)從00:00:00開始考慮,此時分秒針都指向最上方12點方向。12個小時之後,時分秒針再次都指向最上方,完成一個周期,所以只需要計算12小時內三個指標happy的累計“秒數”,然後除以12小時的總秒數就得到了結果(12小時和24小時的結果是一樣的~)。
(3)從00:00:00開始考慮,根據上述條件,可以分別計算出時針分針、時針秒針、分針秒針在12小時中,每一次滿足happy條件的起止時間,使用數組儲存。
(4)需要注意的是,為了滿足happy的條件,既需要判斷順時針夾角1是否滿足條件,也需要判斷該夾角1的對頂角2是否滿足條件。因為夾角1和夾角2都是這兩個指標構成的角度。
(5)使用數軸來表示時間(使用數軸畫一畫會更容易理解),根據數組中儲存的值尋找交集,則可以找到時針分針秒針都happy的時間段。
本題AC參考代碼:
import java.io.BufferedInputStream;import java.text.DecimalFormat;import java.util.Scanner;public class Main {private static double max(double a, double b, double c) {a = a > b ? a : b; // a的值修改為a,b之中較大的那個a = a > c ? a : c; // a的值修改為a,c之中較大的那個(參與計算的a已經是a,b中較大的數,所以最終的a是a,b,c中最大的)return a;}private static double min(double a, double b, double c) {a = a < b ? a : b;a = a < c ? a : c;return a;}public static void main(String[] args) {Scanner cin = new Scanner(new BufferedInputStream(System.in));int total = 12 * 60 * 60;// 記錄兩兩指標之間的起止時間// 用於記錄分針秒針happy起止時間的數組. bms中的b表示begin,ems中的e表示end// 數組大小708,是因為12小時內分針秒針共重合708次,所以happy的起止次數也為708次//(重合708次是事先計算好的)// 為了防止數組溢出,數組大小設定為709double[] bms = new double[709];double[] ems = new double[709];// 用於記錄時針分針happy起止時間的數組.// 時針分針12小時內共重合11次double[] bhm = new double[12];double[] ehm = new double[12];// 用於記錄時針秒針happy起止時間的數組.// 時針分針12小時內共重合719次double[] bhs = new double[720];double[] ehs = new double[720];// 分針秒針每秒相差的度數double dms = 5.9;// 時針分針每秒的度數差double dhm = 11.0 / 120;// 時針秒針每秒的度數差double dhs = 719.0 / 120;double d = cin.nextDouble();while (d != -1) {// 12小時內,happy時間差累計double count = 0;// 計算並填充各個數組的值bms[0] = d / dms; // 分針秒針第一次happy的起始時間(順時針夾角,開始滿足條件)ems[0] = (360.0 - d) / dms; // 分針秒針第一次happy的結束時間(順時針夾角的對頂角,開始不滿足條件)for (int i = 1; i < 709; i++) {// 分針秒針第i次重合之後,滿足happy條件的開始時間bms[i] = (360.0 * i) / dms + bms[0]; // (360*i)/dms:為分針秒針第i次重合的時間ems[i] = (360.0 * i) / dms + ems[0];}// 計算bhm、ehm、 bhs、 ehs的道理和上述相同bhm[0] = d / dhm;ehm[0] = (360.0 - d) / dhm;for (int i = 1; i < 12; i++) {bhm[i] = (360.0 * i) / dhm + bhm[0];ehm[i] = (360.0 * i) / dhm + ehm[0];}bhs[0] = d / dhs;ehs[0] = (360.0 - d) / dhs;for (int i = 1; i < 720; i++) {bhs[i] = (360.0 * i) / dhs + bhs[0];ehs[i] = (360.0 * i) / dhs + ehs[0];}//i、j、k分別用來記錄bhs[i], bms[j], bhm[k]數組的當前訪問位置int i = 0;int j = 0;int k = 0;//時分秒針滿足happy條件的開始時間和結束時間double begin = 0.0;double end = 0.0;while (begin <= total && end <= total) {// 起始時間取較大值begin = max(bhs[i], bms[j], bhm[k]);// 結束時間取較小值end = min(ehs[i], ems[j], ehm[k]);//在一次迴圈中,只會改變i、j、k中的某一個值,將相對最後的那一個向前移動。。。//不太好解釋,畫畫數軸會比較好理解if (end == ehs[i]) {i++;}if (end == ems[j]) {j++;}if (end == ehm[k]) {k++;}if (end > begin && end <= total) {count += (end - begin);}}// 保留三位小數輸出DecimalFormat formatter = new DecimalFormat("#0.000");double result = ((count + 0.00) / total) * 100;System.out.println(formatter.format(result));d = cin.nextDouble();}cin.close();}}
歡迎評論討論指正,不喜勿噴。