Hướng dẫn giải của Góc giữ kim giờ và kim phút


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.

Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.

Bạn phải đăng nhập để mở lời giải này.

Đăng nhập

Tác giả: Hiếu Nguyễn, BQV666666, code_ga_vl, Namdo

Editorial for clkangle: Góc giữ kim giờ và kim phút

Hiểu bài toán

Bài toán yêu cầu tính toán góc giữa kim giờ và kim phút của một chiếc đồng hồ 12 giờ tại một thời điểm cụ thể (h giờ, m phút). Input là hai số nguyên h (0 <= h <= 11) và m (0 <= m <= 59). Output là một số thực được làm tròn đến một chữ số thập phân, biểu diễn góc nhỏ nhất giữa hai kim (luôn nằm trong khoảng [0, 180]).

Các cách tiếp cận

Cách Tính toán trực tiếp theo từng kim
#include <stdio.h>
#include <math.h>

int main() {
    int h, m;
    scanf("%d%d", &h, &m);

    // Tính góc của kim giờ và kim phút
    double hour_angle = (h % 12) * 30 + m * 0.5;
    double minute_angle = m * 6;

    // Tính góc giữa hai kim
    double angle = fabs(hour_angle - minute_angle);

    // Chọn góc nhỏ nhất (nếu lớn hơn 180 thì lấy góc bù)
    if (angle > 180) {
        angle = 360 - angle;
    }

    printf("%.1lf", angle);
    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Phương pháp này chia nhỏ bài toán bằng cách tính vị trí (góc) của từng kim riêng biệt. Kim phút di chuyển 360 độ trong 60 phút, tức là 6 độ mỗi phút. Kim giờ di chuyển 360 độ trong 12 giờ (30 độ mỗi giờ), và di chuyển thêm một phần do kim phút (0.5 độ mỗi phút). Sau khi có hai góc, ta tính hiệu tuyệt đối và sửa lại để đảm bảo kết quả luôn là góc nhỏ nhất (không vượt quá 180 độ).

Cách Công thức gộp (Hiệu số góc)
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main() {
    int a, b;
    scanf("%d%d", &a, &b);

    float kq = abs(30 * a - 5.5 * b);
    if (kq > 180) kq = 360 - kq;
    printf("%.1f", kq);
    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Đây là cách tiếp cận tối ưu hóa phép tính. Ta thiết lập công thức cho góc kim giờ là 30h + 0.5m và góc kim phút là 6*m. Góc chênh lệch là |(30h + 0.5m) - 6m| = |30h - 5.5m|. Phương pháp này gộp các phép nhân lại với nhau để rút gọn số bước tính toán, chỉ giữ lại logic toán học cốt lõi.

Cách Quy đổi sang đơn vị 'phút'
#include <stdio.h>
#include <math.h>

int main(){
    int n, k;
    scanf("%d %d", &n, &k);
    float m = n + (float)k/60;
    float p = (float) k/5;
    float res = (p - m) * 30;
    if(res < 0) res *= (-1);
    if(res > 180) res = 360 - res;
    printf("%.1f", res);
    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Phương pháp này quy đổi tất cả về đơn vị 'phút' để tính toán. Kim giờ chỉ số 'm' (số phút trôi qua từ 12h), kim phút chỉ số 'p' (số 'phút 5' trôi qua). Góc chênh lệch (theo số 'phút 5') là |p - m|. Vì mỗi 'phút 5' tương ứng 30 độ, góc thực tế là |p - m| * 30. Cuối cùng vẫn cần chuẩn hóa về [0, 180].

Phân tích độ phức tạp

Cách tiếp cận Time Space Tên
1 O(1) O(1) Tính toán trực tiếp theo từng kim
2 O(1) O(1) Công thức gộp (Hiệu số góc)
3 O(1) O(1) Quy đổi sang đơn vị 'phút'

Bài học kinh nghiệm

  • Góc kim giờ: 30 độ * số giờ + 0.5 độ * số phút.
  • Góc kim phút: 6 độ * số phút.
  • Góc giữa hai kim là hiệu số góc, nhưng phải lấy giá trị nhỏ nhất giữa hiệu đó và góc bù của nó (360 - hiệu).

Lỗi thường gặp

  • Quên xử lý trường hợp h = 12 (dù input là 0-11, phép chia modulo 12 là thói quen tốt).
  • In sai định dạng số thực (phải là %.1f hoặc %.1lf).
  • Sai công thức góc kim giờ (quên phần di chuyển thêm do kim phút).

Bình luận

Please read the guidelines before commenting.


Không có bình luận tại thời điểm này.