2026.01.05일자 입니다. 기하 1: 직사각형과 삼각형 풀어보았습니다.
1085번 직사각형에서 탈출
문제 링크
(x, y)에서 x=0, y=0, x=w, y=h로 가는 루트 중 최단거리를 구하는 문제입니다.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int x, y, w, h; cin >> x >> y >> w >> h;
w -= x; h -= y; cout << min({ x,y,w,h });
}
x에서 w까지의 거리, y에서 h까지의 거리를 구하여 w, h에 저장한 뒤 x, y, w, h 중 최솟값을 구하였습니다. x에서 0까지, y에서 0까지는 각각 x, y이므로 따로 계산이 필요하지 않습니다.
3009번 네 번째 점
문제 링크
세 점 중 한 번만 등장하는 한 점을 찾는 문제입니다.
#include <iostream>
using namespace std;
int main() {
int x1, y1, x2, y2, x3, y3; cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
if (x1 != x2) cout << ((x1 != x3) ? x1 : x2) << ' '; else cout << x3 << ' ';
if (y1 != y2) cout << ((y1 != y3) ? y1 : y2); else cout << y3;
}
단순 if문을 사용하여 구할 수 있으나 XOR 을 활용한 풀이가 있어 공부해보았습니다.
먼저 XOR(Exclusive OR, 배타적 논리합)은 두 입력이 같으면 0 다르면 1이 되는 연산입니다.
C++ 에서 XOR은 ^ 연산자에 의해 진행되며 비트(Bit) 단위 연산이 진행됩니다.
따라서 두 입력이 같은 경우, 예를 들어 5 ^ 5 = 101 ^ 101 = 000 = 0 이 됩니다.
두 입력이 다를 경우, 예를 들어 0 ^ 7 = 000 ^ 111 = 111 이 됩니다.
XOR을 이용한 코드는 코드는 아래와 같으며 해당 블로그를 참고하였습니다.
#include <iostream>
using namespace std;
int main() {
int x1, y1, x2, y2, x3, y3; cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
cout << int(x1 ^ x2 ^ x3) << ' ' << int(y1 ^ y2 ^ y3);
}
같은 수끼리의 ^ 연산은 0, 0과 어떤 수의 ^ 연산은 해당 수라는 규칙을 이용하여 풀 수 있었습니다.
15894번 수학은 체육과목 입니다.
문제 링크
1개일 때는 4, 2개일 때는 8, 3개일 때는 12로 4의 배수라는 규칙을 찾을 수 있습니다.

실선 부분을 사각형의 선분으로 채워넣는다고 생각하면 아래가 n개일 때의 도형은 사각형 n개로 만들 수 있다는 규칙을 찾을 수 있습니다.
따라서 아래가 n개일 때 도형의 둘레는 사각형 n개의 둘레와 같다는 사실을 알 수 있습니다.
#include <iostream>
using namespace std;
int main() { long long n; cin >> n; cout << n * 4; }
만약 n을 int로 선언한다면 오답이 됩니다.
문제에서 n의 범위는 1 ~ 109입니다. 따라서 결과인 4n의 범위는 4 ~ 4 * 109입니다.
그런데 int의 범위는 -231 ~ 231 - 1으로 약 ± 2 * 109 정도 입니다. 따라서 int는 4n을 모두 저장할 수 없습니다.
만약 범위를 초과하여 저장할 경우 최대/최소 범위를 초과했을 때 값이 순환되어 반대 범위의 값으로 돌아가는 현상인 wrapping이 발생하여 최솟값 미만인 약 - 2 * 109 정도로 떨어집니다.
따라서 -263 ~ 263 - 1의 정수를 저장할 수 있는 long long을 사용해야 합니다.
약 ± 9 * 1018을 저장할 수 있으므로 4n을 안정적으로 저장할 수 있습니다.
0 ~ 232 - 1(약 4 * 109)의 정수를 저장할 수 있는 unsigned int를 사용해도 정답이나 아슬아슬하므로 long long을 사용하는 편이 더 좋을 것 같습니다.
9063번 대지
문제 링크
가장 큰 좌표와 작은 좌표를 구해 빼고 곱하는 문제입니다.
#include <iostream>
using namespace std;
int main() {
int n; cin >> n;
int min_x = 10001, max_x = -10001, min_y = 10001, max_y = -10001;
while (n--) {
int tx, ty; cin >> tx >> ty;
min_x = tx < min_x ? tx : min_x; max_x = tx > max_x ? tx : max_x;
min_y = ty < min_y ? ty : min_y; max_y = ty > max_y ? ty : max_y;
} cout << (max_x - min_x) * (max_y - min_y);
}
입력과 동시에 최댓값, 최솟값을 계산하였습니다.
배열에 저장한 뒤 max/min_element를 사용하는 방법도 고려해보았으나 <algorithm> 헤더 파일이 필요하고, 입력 후 배열을 훑는 것보다 입력과 동시에 계산하는 편이 더욱 효율적이라 생각하여 해당 풀이를 선택하였습니다.
5073번 삼각형과 세 변
문제 링크
조건에 따라 출력하는 간단한 문제입니다.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
while (true) {
int a, b, c; cin >> a >> b >> c;
if (a == 0) break;
if (max({ a, b, c }) * 2 >= a + b + c) cout << "Invalid\n";
else if (a == b && b == c) cout << "Equilateral\n";
else if (a == b || b == c || c == a) cout << "Isosceles\n";
else cout << "Scalene\n";
}
}
가장 긴 변의 길이보다 나머지 두 변의 길이의 합이 길지 않으면 삼각형이 아닙니다.
하지만 입력에서 가장 긴 변이 어디 있는지는 주어지지 않습니다. 따라서 max 함수를 이용하여 가장 긴 변을 구하고, 모든 변의 길이의 합에서 가장 긴 변의 길이를 빼내어 나머지 두 변의 길이를 구할 수 있습니다.
코드로 작성하면 다음과 같은데
max({a, b, c}) >= a + b + c - max({a, b, c})
우변의 max를 좌변으로 넘겨주면
2 * max({a, b, c}) >= a + b + c
max를 한 번만 사용하고도 조건을 만들 수 있습니다.
다른 풀이를 찾아보고 싶어 블로그를 많이 찾아봤지만 if문을 사용하지 않는 코드는 찾을 수 없었습니다.
그리하여 해당 코드의 숏코드를 찾아보았습니다. 다음 코드를 참고하였습니다.
main(a,b,c){while(scanf("%d%d%d",&a,&b,&c),a)puts(a^b|b^c?a<b+c&b<a+c&c<a+b?a==b|b==c|a==c?"Isosceles":"Scalene":"Invalid":"Equilateral");}
해당 코드는 C 표준인 .c에서만 작동하며 C++ 표준인 .cpp에서는 동작하지 않습니다.
먼저 int main(int argc, char* argv[])의 형태가 정석이나 main(a, b, c)로 작성하게 되면 컴파일러가 이를 모두 int형으로 간주합니다.
또한 #include <stdio.h>를 생략하고 scanf, puts 등의 함수를 호출해도 암시적 선언이 됩니다.
while(scanf("%d%d%d",&a,&b,&c),a)에서 whlie 내부의 ,를 콤마 연산자(Comma Operator)라고 부릅니다. 왼쪽에서 오른쪽 순서대로 실행하고 가장 오른쪽 표현식의 값을 조건으로 사용합니다. 따라서 a에 0이 입력된다면 반복이 종료됩니다.
a^b|b^c?...?...:...는 중첩 삼항 연산자를 사용한 코드입니다.
if (a^b | b^c) {
if (a<b+c&b<a+c&c<a+b) {
if (a==b|b==c|a==c) "Isosceles"
else "Scalene"
} else "Invalid"
} else "Equilateral"
해당 코드로 풀어서 작성할 수 있습니다. 여기서 논리 연산자 &&, ||가 아닌 비트 연산자 &, |가 사용되었습니다.
논리 연산자와의 차이점은 비트 연산자는 Short-circuit을 지원하지 않습니다.
Short-circuit이란 false && true는 앞이 false이므로 뒷 부분은 계산하지 않고 false가 반환되는 것을 말합니다.
&은 Short-circuit이 지원되지 않아 false && true에서 true까지 계산합니다.
ptr != NULL && ptr->value == 10라는 식이 있다고 가정합니다. &&은 전자에서 false가 반환되면 후자는 실행되지 않습니다.
하지만 &을 사용하면 전자에서 false가 반환되더라도 후자가 실행되어1.05일자 입니다. 기하 1: 직사각형과 삼각형 풀어보았습니다.
1085번 직사각형에서 탈출
문제 링크
(x, y)에서 x=0, y=0, x=w, y=h로 가는 루트 중 최단거리를 구하는 문제입니다.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int x, y, w, h; cin >> x >> y >> w >> h;
w -= x; h -= y; cout << min({ x,y,w,h });
}
x에서 w까지의 거리, y에서 h까지의 거리를 구하여 w, h에 저장한 뒤 x, y, w, h 중 최솟값을 구하였습니다. x에서 0까지, y에서 0까지는 각각 x, y이므로 따로 계산이 필요하지 않습니다.
3009번 네 번째 점
문제 링크
세 점 중 한 번만 등장하는 한 점을 찾는 문제입니다.
#include <iostream>
using namespace std;
int main() {
int x1, y1, x2, y2, x3, y3; cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
if (x1 != x2) cout << ((x1 != x3) ? x1 : x2) << ' '; else cout << x3 << ' ';
if (y1 != y2) cout << ((y1 != y3) ? y1 : y2); else cout << y3;
}
단순 if문을 사용하여 구할 수 있으나 XOR 을 활용한 풀이가 있어 공부해보았습니다.
먼저 XOR(Exclusive OR, 배타적 논리합)은 두 입력이 같으면 0 다르면 1이 되는 연산입니다.
C++ 에서 XOR은 ^ 연산자에 의해 진행되며 비트(Bit) 단위 연산이 진행됩니다.
따라서 두 입력이 같은 경우, 예를 들어 5 ^ 5 = 101 ^ 101 = 000 = 0 이 됩니다.
두 입력이 다를 경우, 예를 들어 0 ^ 7 = 000 ^ 111 = 111 이 됩니다.
XOR을 이용한 코드는 코드는 아래와 같으며 해당 블로그를 참고하였습니다.
#include <iostream>
using namespace std;
int main() {
int x1, y1, x2, y2, x3, y3; cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
cout << int(x1 ^ x2 ^ x3) << ' ' << int(y1 ^ y2 ^ y3);
}
같은 수끼리의 ^ 연산은 0, 0과 어떤 수의 ^ 연산은 해당 수라는 규칙을 이용하여 풀 수 있었습니다.
15894번 수학은 체육과목 입니다.
문제 링크
1개일 때는 4, 2개일 때는 8, 3개일 때는 12로 4의 배수라는 규칙을 찾을 수 있습니다.

실선 부분을 사각형의 선분으로 채워넣는다고 생각하면 아래가 n개일 때의 도형은 사각형 n개로 만들 수 있다는 규칙을 찾을 수 있습니다.
따라서 아래가 n개일 때 도형의 둘레는 사각형 n개의 둘레와 같다는 사실을 알 수 있습니다.
#include <iostream>
using namespace std;
int main() { long long n; cin >> n; cout << n * 4; }
만약 n을 int로 선언한다면 오답이 됩니다.
문제에서 n의 범위는 1 ~ 109입니다. 따라서 결과인 4n의 범위는 4 ~ 4 * 109입니다.
그런데 int의 범위는 -231 ~ 231 - 1으로 약 ± 2 * 109 정도 입니다. 따라서 int는 4n을 모두 저장할 수 없습니다.
만약 범위를 초과하여 저장할 경우 최대/최소 범위를 초과했을 때 값이 순환되어 반대 범위의 값으로 돌아가는 현상인 wrapping이 발생하여 최솟값 미만인 약 - 2 * 109 정도로 떨어집니다.
따라서 -263 ~ 263 - 1의 정수를 저장할 수 있는 long long을 사용해야 합니다.
약 ± 9 * 1018을 저장할 수 있으므로 4n을 안정적으로 저장할 수 있습니다.
0 ~ 232 - 1(약 4 * 109)의 정수를 저장할 수 있는 unsigned int를 사용해도 정답이나 아슬아슬하므로 long long을 사용하는 편이 더 좋을 것 같습니다.
9063번 대지
문제 링크
가장 큰 좌표와 작은 좌표를 구해 빼고 곱하는 문제입니다.
#include <iostream>
using namespace std;
int main() {
int n; cin >> n;
int min_x = 10001, max_x = -10001, min_y = 10001, max_y = -10001;
while (n--) {
int tx, ty; cin >> tx >> ty;
min_x = tx < min_x ? tx : min_x; max_x = tx > max_x ? tx : max_x;
min_y = ty < min_y ? ty : min_y; max_y = ty > max_y ? ty : max_y;
} cout << (max_x - min_x) * (max_y - min_y);
}
입력과 동시에 최댓값, 최솟값을 계산하였습니다.
배열에 저장한 뒤 max/min_element를 사용하는 방법도 고려해보았으나 <algorithm> 헤더 파일이 필요하고, 입력 후 배열을 훑는 것보다 입력과 동시에 계산하는 편이 더욱 효율적이라 생각하여 해당 풀이를 선택하였습니다.
5073번 삼각형과 세 변
문제 링크
조건에 따라 출력하는 간단한 문제입니다.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
while (true) {
int a, b, c; cin >> a >> b >> c;
if (a == 0) break;
if (max({ a, b, c }) * 2 >= a + b + c) cout << "Invalid\n";
else if (a == b && b == c) cout << "Equilateral\n";
else if (a == b || b == c || c == a) cout << "Isosceles\n";
else cout << "Scalene\n";
}
}
가장 긴 변의 길이보다 나머지 두 변의 길이의 합이 길지 않으면 삼각형이 아닙니다.
하지만 입력에서 가장 긴 변이 어디 있는지는 주어지지 않습니다. 따라서 max 함수를 이용하여 가장 긴 변을 구하고, 모든 변의 길이의 합에서 가장 긴 변의 길이를 빼내어 나머지 두 변의 길이를 구할 수 있습니다.
코드로 작성하면 다음과 같은데
max({a, b, c}) >= a + b + c - max({a, b, c})
우변의 max를 좌변으로 넘겨주면
2 * max({a, b, c}) >= a + b + c
max를 한 번만 사용하고도 조건을 만들 수 있습니다.
다른 풀이를 찾아보고 싶어 블로그를 많이 찾아봤지만 if문을 사용하지 않는 코드는 찾을 수 없었습니다.
그리하여 해당 코드의 숏코드를 찾아보았습니다. 다음 코드를 참고하였습니다.
main(a,b,c){while(scanf("%d%d%d",&a,&b,&c),a)puts(a^b|b^c?a<b+c&b<a+c&c<a+b?a==b|b==c|a==c?"Isosceles":"Scalene":"Invalid":"Equilateral");}
해당 코드는 C 표준인 .c에서만 작동하며 C++ 표준인 .cpp에서는 동작하지 않습니다.
먼저 int main(int argc, char* argv[])의 형태가 정석이나 main(a, b, c)로 작성하게 되면 컴파일러가 이를 모두 int형으로 간주합니다.
또한 #include <stdio.h>를 생략하고 scanf, puts 등의 함수를 호출해도 암시적 선언이 됩니다.
while(scanf("%d%d%d",&a,&b,&c),a)에서 whlie 내부의 ,를 콤마 연산자(Comma Operator)라고 부릅니다. 왼쪽에서 오른쪽 순서대로 실행하고 가장 오른쪽 표현식의 값을 조건으로 사용합니다. 따라서 a에 0이 입력된다면 반복이 종료됩니다.
a^b|b^c?...?...:...는 중첩 삼항 연산자를 사용한 코드입니다.
if (a^b | b^c) {
if (a<b+c&b<a+c&c<a+b) {
if (a==b|b==c|a==c) "Isosceles"
else "Scalene"
} else "Invalid"
} else "Equilateral"
해당 코드로 풀어서 작성할 수 있습니다. 여기서 논리 연산자 &&, ||가 아닌 비트 연산자 &, |가 사용되었습니다.
논리 연산자와의 차이점은 비트 연산자는 Short-circuit을 지원하지 않습니다.
Short-circuit이란 false && true는 앞이 false이므로 뒷 부분은 계산하지 않고 false가 반환되는 것을 말합니다.
&은 Short-circuit이 지원되지 않아 false && true에서 true까지 계산합니다.
ptr != NULL && ptr->value == 10라는 식이 있다고 가정합니다. &&은 전자에서 false가 반환되면 후자는 실행되지 않습니다.
하지만 &을 사용하면 전자에서 false가 반환되더라도 후자가 실행되어 NULL 포인터를 참조하는 상황이 발생할 수 있습니다.
14215번 세 막대
문제 링크
주어진 세 개의 길이로 삼각형을 만드는 문제입니다.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int t[3]; cin >> t[0] >> t[1] >> t[2]; sort(t, t + 3); cout << (t[2] >= t[0] + t[1] ? 2 * (t[0] + t[1]) - 1 : t[0] + t[1] + t[2]);
}
sort 연산으로 배열을 정렬합니다. 정렬 이후 가장 마지막인 2번 인덱스가 가장 긴 변입니다.
가장 긴 변이 나머지 두 변의 길이의 합보다 짧다면 삼각형이므로 모든 변의 합을 구하면 됩니다.
아니라면 삼각형이 될 수 있는 가장 긴 변이 될 수 있는 최댓값을 구해야 합니다. 삼각형의 조건이 가장 긴 변 < 나머지의 합 이고 이는 정수여야 하므로 가장 긴 변이 될 수 있는 최댓값은 나머지의 합 - 1입니다. 따라서 이 경우 둘레는 2 * 나머지의 합 - 1 이 됩니다.
Top comments (0)