일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Android
- androidstudio
- bitmap
- BOJ
- Canvas
- CS
- Database
- DBeaver
- DP
- Ecilpse
- Eclipse
- firebase
- git
- github
- GooglePlayServices
- gradle
- IDE
- IntelliJ
- java
- json
- kotlin
- level2
- linux
- mariadb
- MYSQL
- Paint
- permission
- python
- Sorting
- sourcetree
will come true
[백준] 1193번 - 분수찾기 (Java) 본문
문제
https://www.acmicpc.net/problem/1193
코드
import java.util.Scanner;
// 분수찾기
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count = 1; // i번째
for (int i = 1; ; i++) {
int j = 1;
if (i % 2 == 0) { // 짝수번째 차례에는 위에서부터 시작
for (j = 1; j <= i; j++) {
if (count == n) {
System.out.println(j + "/" + (i - j + 1));
break;
}
count++;
}
} else { // 홀수번째 차례에는 아래에서 부터 시작
for (j = 1; j <= i; j++) {
if (count == n) {
System.out.println((i - j + 1) + "/" + j);
break;
}
count++;
}
}
// for문이 끝까지 진행되지 못 하고 break 조건에 걸렸을 경우
if (j != i + 1) {
break;
}
}
}
}
분수찾기에서 순번을 매기는 순서에 주의하자. 지그재그 방향으로 나아가기 때문에 1/1, 1/2, 2/1, 3/1, 2/2, 1/3... 과 같이 두번째 그림처럼 대각선 라인별로 구분했을 때, 각 라인 별로 진행방향이 달라진다. 한번씩 차례대로 진행 방향이 바뀌기 때문에 짝수 번째 라인에서는 위→아래 방향으로, 홀수 번째 라인에서 아래→위 방향으로 순번을 매긴다고 생각하면 된다.
위에서 2번째 그림과 같이 각 라인 안에서 일정한 규칙에 따라 분수들이 정해진다. 라인 안에 포함된 분수를 i/j 형태로 볼 때 i가 +1씩증가하고, j가 -1씩 감소하는 규칙적인 형태를 취한다.
ex) 2번째 라인 = { 2/1, 1/2 }, 4번째 라인 = {4/1, 3/2, 2/3, 1/4}
이는 이중 for문으로 구현할 수 있다. 바깥쪽 for문 (i번째 라인) + 안쪽 for문 (j번째 분수)
다만, 처음에 설명한 것과 같이 짝수 번째 라인일 때 / 홀수 번째 라인일 때 j의 진행 방향이 다름에 유의하자.
번호를 매기는 순서는 { 1/1 → 1/2, 2/2 → 1/3, 2/2, 3/1 } 이 아니라 { 1/1 → 1/2, 2/2 → 3/1, 2/2, 1/3 } 이다.
이렇게 차례대로 1부터 무한반복으로 순번을 구해나다 입력받은 n번째 순번인 경우(count==n) 해당 순번에서의 분수 값을 String 형태로 형식화해서 출력한 뒤, 이중 for문을 탈출하면 된다.
다른 사람의 코드
다른 사람의 코드를 참고하여 개선한 코드.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int currCount = 1; // 현재 대각선 칸 개수
int prevCountSum = 0; // 이전 대각선 칸 개수 누적 합
while (true) {
// 현재 대각선의 마지막 순번보다 작거나 같음
if (n <= prevCountSum + currCount) {
if (currCount % 2 == 0) { // 대각선 개수가 짝수면 위 → 아래
System.out.println((n - prevCountSum) + "/" + (currCount - (n - prevCountSum - 1)));
} else { // 대각선 개수가 홀수면 아래 → 위
System.out.println((currCount - (n - prevCountSum - 1)) + "/" + (n - prevCountSum));
}
break;
} else {
prevCountSum += currCount;
currCount++; // 대각선 칸 개수는 1칸씩 늘어남 (1, 2, 3, ...)
}
}
}
}
각 대각선의 칸 개수로 n번째 분수가 존재하는 대각선까지 단순에 이동한 뒤 순서를 계산하기 때문에 내가 사용했던 방식에 비해 훨 빠르다. (미리 범위를 줄여두는, 소거법 방식) 단일 반복문이기 때문에 break; 방식도 이중 반복문에 비해 간단하다.
- 분자와 분수의 합이 같은 것끼리 같은 대각선 라인에 위치한다.
- 각 대각선의 칸(분수) 개수 = (분자 + 분수) - 1 개
- 대각선의 칸 개수와 분모+분자의 합 관계를 이용해 해당 대각선에서의 시작 분모, 시작 분자를 알아낼 수 있다.
'Algorithm' 카테고리의 다른 글
[백준] 2775번 - 부녀회장이 될테야 (Java) (0) | 2022.02.08 |
---|---|
[백준] 2869번 - 달팽이는 올라가고 싶다 (Java) (0) | 2022.02.08 |
[백준] 2292번 - 벌집 (Java) (0) | 2022.02.08 |
[백준] 1346번 - 그룹 단어 체커 (Java) (0) | 2022.02.07 |
[백준] 2941번 - 크로아티아 알파벳 (Java) (0) | 2022.02.07 |