반응형

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

 

1018번: 체스판 다시 칠하기

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

www.acmicpc.net

문제

지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M*N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 8*8 크기의 체스판으로 만들려고 한다.

체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.

보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 8*8 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 8*8 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

출력

첫째 줄에 지민이가 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.

 

해설

사실 부르트포스에 해설이랄게 뭐 있을까요? ㅠㅠ

하나하나 다 숫자를 세보면 됩니다!

 

저 같은 경우에는 첫번째 칸이 'B' 또는 'W'로 시작하고, 8x8 크기의 체스판을 칠할때

몇번을 칠하면 원하는 색으로 시작하는 체스판이 완성이 되는지

count하는 함수를 작성했어요.

 

countNeedPating(startRowNum, startColNum, startColor) 함수를 작성했고,

인수로 시작하는 row, col, color을 받아서 8x8을 직접 칠해보면서, count를 해줬습니다.

 

여기서 한가지 집중했던 점은

 

8x8 체스판은 64번을 칠하면 완성이 되는데,

첫번째 칸이 'B'일때와 'W'일때의 색칠해야 하는 횟수를 합치면 64가 된다는 것입니다.

따라서 B나 W로 시작하는 경우의 색칠 횟수 한번만 구하면 나머지 경우도 계산이 됩니다.

 

코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString().split('\n');
 
// input을 미리 정리합니다.
const [height, width] = input[0].split(' ').map(el => parseInt(el))
const originBoard = []
for(let i = 1; i <= height; i++) {
  let row = input[i].split('')
  originBoard.push(row)
}
 
// 우리가 색칠 할 Size를 먼저 정의를 해주었습니다.
// 문제를 풀때 x, y 만 수정하면 작은 경우의 수부터 테스트를 진행 할 수 있거든요.
const SIZE = {x:8, y:8}
 
// 색칠 횟수를 count 하는 함수를 먼저 정의합니다.
// 시작하는 위치에서 부터 SIZE에서 정의한 만큼의 체스판을 색칠해봅니다.
function countNeedPainting(startRowNum, startColNum, startColor) {
  let nextColor = startColor;
  let count = 0;
  // i = row
  for(let i = startRowNum; i < startRowNum + SIZE.x; i++) {
    // j = column
    for(let j = startColNum; j < startColNum + SIZE.y; j++) {
      if(originBoard[i][j] !== nextColor) {
        count++;
      }
      nextColor = nextColor === 'B' ? 'W' : 'B'
    }
    nextColor = nextColor === 'B' ? 'W' : 'B'
  }
  return count;
}
 
// 최소값을 미리 넉넉하게 설정해 뒀습니다.
let min = SIZE.x * SIZE.y;
// 전체 크기에서 체스판을 자를 수 있는 모든 경우의 수를 loop를 돌며 확인합니다.
for(let i = 0 ; i <= height - SIZE.x; i++) {
  for(let j = 0; j <= width - SIZE.y; j++) {
    const blakCount = countNeedPainting(i, j, 'B');
    const whiteCount = (SIZE.x * SIZE.y) - blakCount;
    const currentMin = blakCount > whiteCount ? whiteCount : blakCount
 
    if(min > currentMin) {
      min = currentMin
    }
  }
}
 
console.log(min)
cs
반응형
반응형

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

 

7568번: 덩치

우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩

www.acmicpc.net

문제

우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x > p 그리고 y > q 이라면 우리는 A의 덩치가 B의 덩치보다 "더 크다"고 말한다. 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56, 177), (45, 165) 라고 한다면 A의 덩치가 B보다 큰 셈이 된다. 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다. 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55, 173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, "덩치"로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.

N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 "큰 덩치"의 사람의 수로 정해진다. 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다. 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다. 아래는 5명으로 이루어진 집단에서 각 사람의 덩치와 그 등수가 표시된 표이다.

이름(몸무게, 키)덩치 등수

A (55, 185) 2
B (58, 183) 2
C (88, 186) 1
D (60, 175) 2
E (46, 155) 5

위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다. 그리고 A, B, D 각각의 덩치보다 큰 사람은 C뿐이므로 이들은 모두 2등이 된다. 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다. 위 경우에 3등과 4등은 존재하지 않는다. 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.

입력

첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.

출력

여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백문자로 분리되어야 한다.

 

해설

등수를 구하는 문제이기 때문에 정렬을 하고, 확실하지 않은 경우는 rank를 공동으로 부여하면 된다.

 

하지만 위 같은 방법으로 구현을 할 시에 귀찮다....

 

정렬(nLogn) + rank(n) 으로 구현이 가능하지만 n^2인 방법으로 문제를 풀었다.

 

문제를 푼 접근 방법은

 

"Rank는 결국 나보다 더치가 큰 사람의 숫자 + 1" 이다.

 

나보다 큰 사람이 없으면 rank가 1이 되고, 나보다 큰 사람이 9명이면 내 rank는 10이 된다.

 

다음 코드는 node를 이용하여 구현한 결과이다.

 

코드

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
32
33
const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString().split('\n');
const num = parseInt(input[0]);
 
// Person class를 통해 문제를 풀어보겠습니다.
class Person {
  constructor(weight, height) {
    this.weight = weight;
    this.height = height;
    this.rank = 0;
  }
}
 
const people = []
 
// input 을 통해서 모든 사람의 정보를 people에 저장을 합니다.
for(let i = 1; i <= num; i++) {
  const [weight, height] = input[i].split(" ");
  const person = new Person(weight, height);
  people.push(person);
}
 
// 전체 사람 중에서 '나'보다 덩치가 큰 사람을 count 하고 +1을 하면 내 rank가 됩니다.
for(let i = 0; i < people.length; i++) {
  let currentPeople = people[i];
  const biggerPeople = people.filter(person => person.weight > currentPeople.weight && person.height > currentPeople.height);
  currentPeople.rank = biggerPeople.length + 1;
}
 
// 결과를 출력합니다.
for(let person of people) {
  console.log(person.rank);
}
cs
반응형
반응형

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

 

2231번: 분해합

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이

www.acmicpc.net

문제

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다.

자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

출력

첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

 

해설

문제에서 얻을 수 있는 힌트를 먼저 살펴보면

 

"가장 작은 생성자"

"없을 수도 있다"

 

두가지 정도를 찾을 수 있을것 같다.

 

분해합은 반드시 생성자보다 크기 때문에 0부터 시작하면서 하나씩 생성자가 될 수 있는지 확인을 하면서 진행하면 문제를 풀 수 있다.

 

0부터 시작하는 이유는 "가장 작은 생성자"를 찾는 문제이기 때문이다.

 

만약 "가장 큰 생성자"를 찾는 문제라면 N 부터 0까지 진행하면 된다.

 

쉬운 문제이기 때문에 설명은 코드 주석으로 적어 놓았다.

 

코드

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
const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString();
 
const N = parseInt(input)
 
let M = 0
for(let i = 0; i < N; i++) {
  //각 자리수와 후보값의 합을 구하기 위한 변수
  let sum = 0;
 
  // 0부터 시작하는 후보값
  const candidateValue = i;
 
  //각 자리수를 구하기 위해서 숫자를 string으로 변환하여 계산한다.
  const stringValue = candidateValue.toString()
 
  for(let j = 0; j < stringValue.length; j++) {
    sum += parseInt(stringValue[j])
  }
 
  sum += candidateValue;
 
  if(sum == N) {
    M = candidateValue
    break;
  }
}
 
console.log(M)
cs
반응형

+ Recent posts