백준(C, C++)/실버

[C/C++] 백준 1004번 - 어린 왕자, 새롭게 Class로 풀어보자

치킨먹고싶어요 2022. 5. 25. 14:48

https://www.acmicpc.net/problem/1004

 

1004번: 어린 왕자

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 첫째 줄에 출발점 (x1, y1)과 도착점 (x2, y2)이 주어진다. 두 번째 줄에는 행성계의 개수 n이 주

www.acmicpc.net

클래스로 풀어보았습니다.

 

완성된 코드
#include <iostream>
#include <cmath>
using namespace std;
static const auto fastio = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    return 0;
}();
class space {
    int y1, x1, y2, x2, ans = 0;
public:
    space(int y1, int x1, int y2, int x2);
    void calculate(int y, int x, int r);
    bool circle1(int y, int x, int r);
    bool circle2(int y, int x, int r);
    bool circle3(int y, int x, int r);
    void print();
};
space::space(int y1, int x1, int y2, int x2) {
    this->y1 = y1; this->x1 = x1; this->y2 = y2; this->x2 = x2; 
}
void space::calculate(int y, int x, int r) {
    this->ans += !circle3(y, x, r) ?  circle1(y, x, r) + circle2(y, x, r) : 0;
}
auto space::circle1(int y, int x, int r) -> bool {
    if (pow(this->y2 - y, 2+ pow(this->x2 - x, 2< pow(r, 2)) return true;
    else return false;
}
auto space::circle2(int y, int x, int r) -> bool {
     if (pow(this->y1 - y, 2+ pow(this->x1 - x, 2< pow(r, 2)) return true;
     else return false;
}
auto space::circle3(int y, int x, int r) -> bool {
    if (pow(this->y1 - y, 2+ pow(this->x1 - x, 2< pow(r, 2) and 
        pow(this->y2 - y, 2+ pow(this->x2 - x, 2< pow(r, 2)) return true;
    else return false;
}
 
void space::print() {
    cout << ans << "\n";
}
auto main() -> int {
    int y1, x1, y2, x2, n, t, T, y, x, r; cin >> T;
    for (;T-->0;) {
        cin >> y1 >> x1 >> y2 >> x2;
        space s(y1, x1, y2, x2);
        cin >> n;
        for(;n-->0;) {
            cin >> y >> x >> r;
            s.calculate(y, x, r);
        }
        s.print();
    }
    return 0;
}
 
c

문제요약

여러 원에 둘러 쌓인 두 점이 서로 만나려면 경계를 몇 번 지나야 하는가? 

 

생각의 흐름

출발점에서 도착점으로 갈 때, 꼭 직선으로 가지 않아도 되네? 

어린왕자


-> 점들을 둘러싼 원의 개수가 중요하네? -> 점이 원 안에 있을 때 원의 개수를 카운트하면 될까?
-> 그런데 출발점과 도착점을 모두 둘러싼 원이면? -> 제외해야 하네
-> 모두 둘러싼 원을 제외하고, 출발점과 도착점을 둘러싼 원의 개수를 카운트하자!

 

점이 원 안에 있는지 아닌지 어떻게 알지? -> 반지름보다 점과 원의 중심거리가 작다면 원 안에 있는구나! -> 유클리드 거리를 사용해야 겠구나! 

코드 설명
#include <iostream>
#include <cmath>
using namespace std;
static const auto fastio = []() { // 빠른 입출력 람다로 출력
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    return 0;
}();
class space { 
    int y1, x1, y2, x2, ans = 0//private인자로 외부에서 접근하지 못하게 하였습니다.
public:
    space(int y1, int x1, int y2, int x2); // 생성자
    void calculate(int y, int x, int r); // 각 원을 계산합니다.
    bool circle1(int y, int x, int r); // 도착점을 둘러싼 원인지 계산합니다.
    bool circle2(int y, int x, int r); // 출발점을 둘러싼 원인지 계산합니다.
    bool circle3(int y, int x, int r); // 동시에 둘러싼 원인지 계산합니다.
    void print(); // 출력
};
space::space(int y1, int x1, int y2, int x2) { // 생성자입니다.
    this->y1 = y1; this->x1 = x1; this->y2 = y2; this->x2 = x2; //this->는 private인자를 접근합니다. 
}
void space::calculate(int y, int x, int r) { // 메인 계산입니다.
    this->ans += !circle3(y, x, r) ?  circle1(y, x, r) + circle2(y, x, r) : 0;
}
auto space::circle1(int y, int x, int r) -> bool { // 도착점을 둘러싼 원인지 계산합니다.
    if (pow(this->y2 - y, 2+ pow(this->x2 - x, 2< pow(r, 2)) return true// 반지름 보다 원의 중심과 도착점 사이의 거리가 작다면, 점이 원 안에 있습니다.
    else return false;
}
auto space::circle2(int y, int x, int r) -> bool { // 출발점을 둘러싼 원인지 계산합니다.
     if (pow(this->y1 - y, 2+ pow(this->x1 - x, 2< pow(r, 2)) return true// 반지름 보다 원의 중심과 출발점 사이의 거리가 작다면, 점이 원 안에 있습니다.
     else return false;
}
auto space::circle3(int y, int x, int r) -> bool { // 동시에 둘러싼 원인지 계산합니다.
    if (pow(this->y1 - y, 2+ pow(this->x1 - x, 2< pow(r, 2) and 
        pow(this->y2 - y, 2+ pow(this->x2 - x, 2< pow(r, 2)) return true;
    else return false;
}
 
void space::print() {
    cout << ans << "\n";
}
auto main() -> int {
    int y1, x1, y2, x2, n, t, T, y, x, r; cin >> T;
    for (;T-->0;) { // while (T--)와 같습니다. T-- > 0임
        cin >> y1 >> x1 >> y2 >> x2;
        space s(y1, x1, y2, x2); // 생성자로 출발 점과 도착 점을 넘겨주어야 합니다.
        cin >> n;
        for(;n-->0;) {
            cin >> y >> x >> r;
            s.calculate(y, x, r); // 매번 원이 입력될때 마다, 카운트가 되는지 검사합니다.
        }
        s.print(); // 카운트를 출력합니다.
    }
    return 0;
}
cs

 

 

PS: 아래의 코드는 람다 함수로 C++빠른입출력이 자동적으로 실행됩니다.

static const auto fastio = []() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    return 0;
}();
cs