C++/모두의코드
씹어먹는 C++ - <4 - 2. 클래스의 세계로 오신 것을 환영합니다. (함수의 오버로딩, 생성자)>
둠치킨
2022. 1. 16. 23:34
생각 해볼 문제(modoocode C++)
문제 1
Date 클래스에 여러가지 생성자들을 추가해보세요 (난이도 : 下)
-> 이미 저번 4-1 글에서 생성자를 추가한 코드로 올렸으므로 패스!
문제 2
수학 관련 소프트웨어를 만드는 회사에서 의뢰가 들어왔습니다. 중학생용 기하학 소프트웨워를 만드는 것인데요, 클래스는 총 두 개로 하나는 Point 로 점에 관한 정보를 담는 것이고 다른 하나는 Geometry 로 점들을 가지고 연산을 하는 클래스 입니다. 즉 아래와 같은 두 클래스의 함수들을 모두 정의하세요 (난이도 : 上)
class Point {
int x, y;
public:
Point(int pos_x, int pos_y);
};
class Geometry {
public:
Geometry() {
num_points = 0;
}
void AddPoint(const Point &point) {
point_array[num_points ++] = new Point(point.x, point.y);
}
// 모든 점들 간의 거리를 출력하는 함수 입니다.
void PrintDistance();
// 모든 점들을 잇는 직선들 간의 교점의 수를 출력해주는 함수 입니다.
// 참고적으로 임의의 두 점을 잇는 직선의 방정식을 f(x,y) = ax+by+c = 0
// 이라고 할 때 임의의 다른 두 점 (x1, y1) 과 (x2, y2) 가 f(x,y)=0 을 기준으로
// 서로 다른 부분에 있을 조건은 f(x1, y1) * f(x2, y2) <= 0 이면 됩니다.
void PrintNumMeets();
private:
// 점 100 개를 보관하는 배열.
Point* point_array[100];
int num_points;
};
풀이
#include <iostream>
#include <cmath>
class Point {
int x, y;
public:
Point(int pos_x, int pos_y) : x(pos_x), y(pos_y)
{ }
int GetX() const { return x; }
int GetY() const { return y; }
};
class Geometry {
private:
Point* point_array[100]; // 점 100개를 보관하는 배열
int num_points;
public:
Geometry() : num_points(0)
{ }
~Geometry()
{
for (int i = 0; i < num_points; i++)
delete point_array[i];
}
void AddPoint(const Point& point) {
point_array[num_points++] = new Point(point.GetX(), point.GetY());
}
// 모든 점들 간의 거리를 출력하는 함수입니다.
void PrintDistance();
// 모든 점들을 잇는 직선들 간의 교점의 수를 출력해주는 함수입니다.
void PrintNumMeets();
};
void Geometry::PrintDistance()
{
for (int i = 0; i < num_points-1; i++)
{
for (int j = i + 1; j < num_points; j++)
{
std::cout << i + 1 << "번째 점과 " << j + 1 << "번째 점 사이의 거리는 "
<< sqrt(pow(point_array[i]->GetX() - point_array[j]->GetX(), 2)+ pow(point_array[i]->GetY() - point_array[j]->GetY(), 2))<<"입니다.\n";
}
}
}
void Geometry::PrintNumMeets()
{
// 만들 수 있는 직선은 총 num_points*(num_points-1)/2 개이다.
// 직선의 방정식 계수 a, b, c를 0으로 초기화
// 직선의 방정식 : a*x + b*y + c = 0
const int NUM_OF_LINES = num_points*(num_points-1)/2;
// 첫번째[0] : 직선의 방정식 계수 a
// 두번째[1] : 직선의 방정식 계수 b
// 세번째[2] : 직선의 방정식 계수 c
// 네번째[3] : 직선의 방정식을 만드는 point1의 index
// 다섯번째[4] : 직선의 방정식을 만드는 point2의 index
int coefficients[100000][5] = {0, };
if (NUM_OF_LINES > 100000)
{
std::cout << "직선의 개수가 너무 많아 계산이 불가합니다." << std::endl;
return;
}
// 직선의 방정식 계수 a, b, c를 구한다.
int x1 = 0, y1 = 0;
int x2 = 0, y2 = 0;
int nth_line = 0;
for (int i = 0; i < num_points -1; i++) {
for (int j = 0; j < num_points; j++) {
x1 = point_array[i]->GetX();
y1 = point_array[i]->GetY();
x2 = point_array[j]->GetX();
y2 = point_array[j]->GetY();
coefficients[nth_line][0] = y2 - y1; // a
coefficients[nth_line][1] = x1 - x2; // b
coefficients[nth_line][2] = x1*y1 - 2*x1*y2 + x2*y2; // c
coefficients[nth_line][3] = i;
coefficients[nth_line][4] = j;
nth_line++;
}
}
// 직선이 만나는 포인트의 개수를 구한다.
int sum_of_meets = 0;
for (int i = 0; i < NUM_OF_LINES; i++) {
for (int j = 0; j < num_points - 1; j++) {
for (int k = j+1 ; k < num_points; k++) {
// 직선의 방정식을 세운 포인트는 넘어가기
if (coefficients[i][3] == j || coefficients[i][3] == k) {
continue;
}
x1 = point_array[j]->GetX();
y1 = point_array[j]->GetY();
x2 = point_array[k]->GetX();
y2 = point_array[k]->GetY();
// 두 포인트가 직선 기준으로 서로 반대면에 있는지 확인
if ((coefficients[i][0]*x1 + coefficients[i][1]*y1 + coefficients[i][2]) * (coefficients[i][0]*x2 + coefficients[i][1]*y2 + coefficients[i][2]) <= 0) {
sum_of_meets++;
}
}
}
}
std::cout << std::endl;
std::cout << "직선의 개수는 " << NUM_OF_LINES << "개 입니다." << std::endl;
if(sum_of_meets%2!=0)
std::cout << "직선의 방정식이 교차하는 점의 개수는 " << sum_of_meets/2 + 1 << "개 이다." << '\n';
else
std::cout << "직선의 방정식이 교차하는 점의 개수는 " << sum_of_meets/2 << "개 이다." << '\n';
}
int main() {
// 테스트
Point pos1(1, 2), pos2(3, 1), pos3(-1, -4), pos4(5,2);
Geometry Geo;
Geo.AddPoint(pos1);
Geo.AddPoint(pos2);
Geo.AddPoint(pos3);
Geo.AddPoint(pos4);
Geo.PrintDistance();
Geo.PrintNumMeets();
return 0;
}