반응형

https://swexpertacademy.com/main/code/problem/problemDetail.do?problemLevel=3&contestProbId=AV13_BWKACUCFAYh&categoryId=AV13_BWKACUCFAYh&categoryType=CODE&problemTitle=&orderBy=INQUERY_COUNT&selectCodeLang=ALL&select-1=3&pageSize=10&pageIndex=1

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

난이도⭐⭐⭐

 

 

✅ 문제 풀이
  • 이 문제의 핵심은 굳이 100*100의 배열에 입력을 저장할 필요 없이, 입력을 받으면서 누적합을 구하고, max를 갱신해 나가면 된다는 것이다.
  • 입력을 받을 때, 행을 기준으로 열들을 받는다. 따라서 2중 for문을 사용한다.
  • 2중 for문에서 행이 먼저 돌기 때문에, 한 행의 값을 입력받을 때 100개의 열 값을 받는다.
  • 따라서 row는 각 행마다 누적합을 구하고, 현재의 max와 비교해서 큰 값을 갱신한다.
  • col은 각 행마다 한번에 100개씩 주어진다. 따라서 크기가 100인 배열을 선언해서, 해당 열에 누적하도록 하였다.
  • 열의 최대값은 2중 for문이 끝난 후, 구해진 누적값들을 서로 비교해 최대를 가리고, 현재의 max와 비교해 갱신한다.
  • 대각선은, 2중 for문에서 현재의 행과 열이 같은 값이면(if) 오른쪽방향 대각선의 누적합에, 행과 열을 더했을 때 99이면(else if) 왼쪽방향 대각선의 누적합에 더하도록 하였다. 마찬가지로 2중 for문이 끝난 후 두 값중 max를 구하고, 현재의 max와 비교해 갱신한다.
  • 최종 max를 출력한다.

 

✏ 코드 전문
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	for (int i = 0; i < 10; i++) {
		int t;
		cin >> t;//test case number

		vector<int> col(100,0);
		int rcross = 0;
		int lcross = 0;

		int m = 0;

		for (int j = 0; j < 100; j++) {
			int row = 0;
			for (int k = 0; k < 100; k++) {
				int temp;
				cin >> temp;
				row += temp;
				col[k] += temp;
				if (j == k) rcross += temp;
				else if ((j + k) == 99) lcross += temp;
			}
			m = max(m, row);
		}
		
		for (int j = 0; j < 100; j++) {
			m = max(m, col[j]);
		}

		m = max(m, max(rcross, lcross));
		
		cout << "#" << t << " " << m << "\n";

	}
	return 0;
}
반응형
반응형

https://swexpertacademy.com/main/code/problem/problemDetail.do?problemLevel=3&contestProbId=AV134DPqAA8CFAYh&categoryId=AV134DPqAA8CFAYh&categoryType=CODE&problemTitle=&orderBy=INQUERY_COUNT&selectCodeLang=ALL&select-1=3&pageSize=10&pageIndex=1

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

 

난이도 D3 ⭐⭐⭐

 

✅ 문제 풀이
  • 처음 두 건물과, 마지막 두 건물은 항상 높이가 0이다.
  • 따라서 세번째 건물부터 기준으로하여, 앞에 두 건물과 뒤에 두 건물 보다 큰지 확인한다.
  • 앞 뒤로 총 4개의 건물보다 크다면, 기준이 되는 현재 건물의 높이에서 4개 건물 중 가장 큰 건물의 높이를 뺀 값이 뷰를 확보할 수 있는 세대 수가 된다.
  • 이를 모든 건물에 대해서 반복하며 세대 수를 누적해가면, 각 테스트케이스의 답이 된다.

 

 

✏ 코드 전문
#include<iostream>
#include<vector>
#include<algorithm>
 
using namespace std;
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    //freopen("input.txt", "r", stdin);
    for (int i = 1; i <= 10; i++) {
        int n;
        cin >> n;
        vector<int> arr;
        for (int j = 0; j < n; j++) {
            int temp;
            cin >> temp;
            arr.push_back(temp);
        }
 
        int count = 0;
        for (int j = 2; j < n-2; j++) {
            int cent = arr[j];
            if (arr[j - 2] < cent && arr[j - 1] < cent && arr[j + 1] < cent && arr[j + 2] < cent) {
                int m1 = max(arr[j - 2], arr[j - 1]);
                int m2 = max(arr[j + 1], arr[j + 2]);
                count += cent - (max(m1, m2));
            }
        }
 
        cout << "#" << i << " " << count << "\n";
    }
    return 0;
}
반응형

'CO-TE > 삼성 아카데미' 카테고리의 다른 글

[DX] 1208번 C++ "Flatten" 풀이 / 정렬, 구현  (0) 2023.12.29
반응형

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

 

14503번: 로봇 청소기

첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$  둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽

www.acmicpc.net

 

 

 

💡 로봇 청소기

 

 

 

✅ 문제 풀이
문제를 풀기 전에 지문을 완벽하게 해석해야 한다. 질문게시판을 보면 알겠지만, 문제 해석에 어려움이 많아보인다.

 

  • 로봇청소기는 입력으로 주어지는 (r,c)에서 출발하고 방향도 입력으로 주어지는 d를 향하여 시작한다.
  • 이때 d는 북쪽일 경우 0, 동쪽일 경우 1, 남쪽일 경우 2, 서쪽일 경우 3이다.
    나는 여기서 동쪽과 서쪽을 반대로 생각하는 실수로 인해 자꾸 틀렸습니다가 떠서 알고리즘의 문제인가 싶었다..
  • 방의 상태는 2차원 arr벡터에, 청소를 한 칸의 횟수는 count에 저장한다.
  • 그리고 다음 과정을 while문을 통해서 반복해주면 된다.
  1. 현재 칸이 청소가 안되어 있으면, 즉 0이면 count를 하나 증가시켜주고 현재 칸의 값을 2로 바꾸어준다.
    2로 하는 이유는 청소가 안된 0과 벽인 1을 구분하기 위함이다.
  2. 그리고 현재 칸에서 동서남북에 있는 칸 중 청소가 안된 칸이 있는지 확인한다. 이때 어디가 청소가 안된 칸인지 정확히 알 필요는 없다. 그냥 청소가 안된 칸이 있다면 bool타입의 clean을 false로 바꾸어주면 된다.
  3. 만약(if) 현재 칸에서 동서남북에 있는 칸 중 청소가 안된 칸이 없다면 clean이 true일 것이다. 따라서 clean이 true이면 다음을 따른다.
    3-A. 만약(if) 현재 방향에서 한칸 뒤가 벽이 아니라면, 즉 1이 아니라면 후진할 수 있는 것이기 때문에 r과 c를 한칸 후진한 좌표로 갱신해준다. 이 로직을 수행하고 나면 다시 while문의 1번으로 돌아가게 될 것이다.
    3-B. 만약 현재 방향에서 한칸 뒤가 벽이라면(else), 즉 1이라면 현재 상태에서 청소를 멈춘다. 따라서 count를 출력하고 return 0;을 함으로써 while문을 끝내고 프로그램을 종료한다.
  4.  3과 같지 않다면(else), 즉 주변에 청소할 칸이 하나라도 있으면 clean이 false일 것이다. 따라서 clean이 false이면 다음을 따른다. 
    4-A. 무조건 현재 방향에서 왼쪽(반시계방향)으로 90도 돌린다. 즉 현재 방향이 북이라면 서로, 서라면 남으로, 남이라면 동으로, 동이라면 북으로 돌아간다. 따라서 숫자로 보면 0>>3>>2>>1>>0...방향이다.
    이는 (d+3)을 4로 나눈 나머지와 같아진다. 따라서 d를 (d+3)%4로 갱신해 주면 된다.
    4-B. 그리고 갱신된 방향으로 한칸 앞이 청소가 안되어 있으면 r과 c를 한칸 앞인 좌표로 갱신해준다. 이 로직을 수행하고 나면 다시 while문의 1번으로 돌아가게 될 것이다.
  5. while문을 끝내고 난 뒤에는 count를 출력하도록 한다. 

 

 

✏ 코드 전문
#include<iostream>
#include<vector>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int n, m;
	cin >> n >> m;
	int r, c, d;
	cin >> r >> c >> d;

	vector<vector<int>> arr(n, vector<int> (m));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
		}
	}

	int count = 0;

	int dx[] = { -1,1,0,0 };
	int dy[] = { 0,0,-1,1 };

	while (1) {
		if (arr[r][c] == 0) {//현재 위치가 벽이 아니고, 청소가 안된 곳이라면
			count++;
			arr[r][c] = 2;//청소를 완료하면 2로 채운다
		}
		
		bool clean = true;

		for (int i = 0; i < 4; i++) {
			int x = r + dx[i];
			int y = c + dy[i];
			
			if (arr[x][y] == 0) {
				clean = false;//하나라도 청소안된 곳이있으면 바로 빠져나옴
				break;
			}
			
		}
		if (clean) {//주변에 청소할데가 없으면
			int bx, by;
			if (d == 0) {//북
				bx = r + 1;
				by = c;
			}
			else if (d == 1) {//동
				bx = r;
				by = c - 1;
			}
			else if (d == 2) {//남
				bx = r - 1;
				by = c;
			}
			else {//서
				bx = r;
				by = c + 1;
			}

			if (arr[bx][by] != 1) {//후진할 수 있으면
				r = bx;
				c = by;
			}
			else {
				cout << count;
				return 0;//중단
			}
		}
		//0>>3>>2>>1>>0
		else{//청소할데가 있으면
			d = (d + 3) % 4;//회전=반시례로 90도는 시계로 270도니까
			if (d == 0) {//북
				if (arr[r - 1][c] == 0) {
					r = r - 1;
				}
			}
			else if (d == 1) {//동
				if (arr[r][c + 1] == 0) {
					c = c + 1;
				}
			}
			else if (d == 2) {//남
				if (arr[r + 1][c] == 0) {
					r = r + 1;
				}
			}
			else {//서
				if (arr[r][c - 1] == 0) {
					c = c - 1;
				}
			}
		}
	}

	cout << count;

	return 0;
}
반응형
반응형

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

 

1388번: 바닥 장식

형택이는 건축가이다. 지금 막 형택이는 형택이의 남자 친구 기훈이의 집을 막 완성시켰다. 형택이는 기훈이 방의 바닥 장식을 디자인했고, 이제 몇 개의 나무 판자가 필요한지 궁금해졌다. 나

www.acmicpc.net

 

 

💡 바닥 장식

형택이는 건축가이다. 지금 막 형택이는 형택이의 남자 친구 기훈이의 집을 막 완성시켰다. 형택이는 기훈이 방의 바닥 장식을 디자인했고, 이제 몇 개의 나무 판자가 필요한지 궁금해졌다. 나무 판자는 크기 1의 너비를 가졌고, 양수의 길이를 가지고 있다. 기훈이 방은 직사각형 모양이고, 방 안에는 벽과 평행한 모양의 정사각형으로 나누어져 있다.이제 ‘-’와 ‘|’로 이루어진 바닥 장식 모양이 주어진다. 만약 두 개의 ‘-’가 인접해 있고, 같은 행에 있다면, 두 개는 같은 나무 판자이고, 두 개의 ‘|’가 인접해 있고, 같은 열에 있다면, 두 개는 같은 나무 판자이다.기훈이의 방 바닥을 장식하는데 필요한 나무 판자의 개수를 출력하는 프로그램을 작성하시오.

[입력]
첫째 줄에 방 바닥의 세로 크기N과 가로 크기 M이 주어진다. 둘째 줄부터 N개의 줄에 M개의 문자가 주어진다. 이것은 바닥 장식 모양이고, '-‘와 ’|‘로만 이루어져 있다. N과 M은 50 이하인 자연수이다.

[출력]
첫째 줄에 문제의 정답을 출력한다.

 

 

✅ 문제 풀이
  • 문제에서 주어진 조건을 고려하기만 하면 쉽게 풀리는 문제이다.
  • 같은 행에서 -가 반복된다면 같은 판자인것이고, 같은 열에서 |가 반복된다면 같은 판자인 것이다.
  • 먼저 크기가 N*M인 배열에 -와 |를 입력 받고, N*M만큼 순회한다.
  • i는 행의 번호, j는 열의 번호인데, 행을 순회할 때마다 첫번째 값을 일단 row라는 변수에 저장해 두고, 이 값을 비교하면서 몇개의 나무 판자가 필요한지 카운트 할 것이다. 이때 각 행의 첫번째 요소는 비교 기준이 되므로 일단 count를 하나 올리고 시작한다.
  • 일단 현재의 row가 -인지 |인지 상관없이, 동일한 행안의 요소들을 비교하면서 현재 row와 현재 순회한 값 arr[i][j]가 다르다면 count해준다.
  • 그런다음, 두번째 줄 행부터 앞에 행의 동일한 열에 있는 값과 현재 값을 비교해서, 동일하면서 |이면 count를 하나 빼준다.
  • 그러면 -로는 연속한 것끼리 하나의 판자로, |로 연속한 것끼리 하나의 판자로 계산되어 최종 필요한 판자의 개수를 구할 수 있게 된다. 

 

✏ 코드 전문
#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int N, M;
	cin >> N >> M;

	vector<vector<char>> arr(N);

	for (int i = 0; i < N; i++) {
		string str;
		cin >> str;

		for (int j = 0; j < str.length(); j++) {
			arr[i].push_back(str[j]);
		}
	}

	int count = 0;

	for (int i = 0; i < N; i++) {
		char row = arr[i][0];
		count++;

		if (i > 0 && row == '|'&&row == arr[i - 1][0]) count--;

		for (int j = 1; j < M; j++) {
			if (row != arr[i][j]||(row==arr[i][j] && row=='|')) {
				count++;
				row = arr[i][j];
			}
			if (i > 0 && arr[i][j] == '|'&&arr[i][j] == arr[i - 1][j]) count--;
		}
	}

	cout << count;

	return 0;
}
반응형
반응형

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

 

1475번: 방 번호

첫째 줄에 다솜이의 방 번호 N이 주어진다. N은 1,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

 

💡 방 번호
다솜이는 은진이의 옆집에 새로 이사왔다. 다솜이는 자기 방 번호를 예쁜 플라스틱 숫자로 문에 붙이려고 한다.
다솜이의 옆집에서는 플라스틱 숫자를 한 세트로 판다. 한 세트에는 0번부터 9번까지 숫자가 하나씩 들어있다. 다솜이의 방 번호가 주어졌을 때, 필요한 세트의 개수의 최솟값을 출력하시오. (6은 9를 뒤집어서 이용할 수 있고, 9는 6을 뒤집어서 이용할 수 있다.)

[입력]
첫째 줄에 다솜이의 방 번호 N이 주어진다. N은 1,000,000보다 작거나 같은 자연수이다.

[출력]
첫째 줄에 필요한 세트의 개수를 출력한다.

 

 

✅ 문제 풀이
  • 주어진 방번호 N의 각 자리 수를 구해야한다.
    N을 10으로 나눈 나머지를 구하면 된다.
  • 그리고 그 값을 카운트 해준 후, N을 10으로 나눈 몫으로 갱신한다.
  • 카운트 하기 위해서 0부터 9까지의 출현 빈도를 저장할 배열을 선언해준다.
  • 만약 각 자리의 수가 6또는 9이면, 6번 인덱스와 9번 인덱스의 값을 비교해서 똑같은 경우 6에 먼저 카운트 되도록 하고, 아니면 9에 카운트 되도록 한다.
    6과 9는 뒤집어서 서로를 사용할 수 있기 때문이다.
  • 그렇지 않다면 그냥 그 수에 해당하는 인덱스의 값에 카운트 되도록 한다.
  • 필요한 상자수는 배열에서 가장 MAX인 값과 같게 된다.

 

✏ 코드 전문
#include<iostream>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int arr[10] = { 0 };
	int N;
	cin >> N;

	while (N > 0) {
		if (N % 10 == 6 || N % 10 == 9) {
			if (arr[6] == arr[9]) arr[6]++;
			else arr[9]++;
		}
		else arr[N % 10]++;

		N /= 10;
	}

	int max = arr[0];
	for (int i = 1; i < 10; i++) {
		if (max < arr[i]) max = arr[i];
	}

	cout << max;

	return 0;
}
반응형
반응형

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

 

1051번: 숫자 정사각형

N×M크기의 직사각형이 있다. 각 칸에는 한 자리 숫자가 적혀 있다. 이 직사각형에서 꼭짓점에 쓰여 있는 수가 모두 같은 가장 큰 정사각형을 찾는 프로그램을 작성하시오. 이때, 정사각형은 행

www.acmicpc.net

 

💡 숫자 정사각형
N×M크기의 직사각형이 있다. 각 칸에는 한 자리 숫자가 적혀 있다. 이 직사각형에서 꼭짓점에 쓰여 있는 수가 모두 같은 가장 큰 정사각형을 찾는 프로그램을 작성하시오. 이때, 정사각형은 행 또는 열에 평행해야 한다.

예제 입력

3 5
42101
22100
22101

출력

9

 

✅ 문제 풀이

주어진 행렬에서 가능한 모든 정사각형을 구해야 함을 알 수 있다. 따라서 이 문제는 무식하게 다 접근하는 브루트포스 알고리즘을 이용해야 한다.

 

  • 먼저 입력의 형태를 보자. 입력으로 들어오는 행렬 값이 공백으로 구분되어 있지않고 붙어있다.
    => 따라서 string으로 받고, 한 문자씩 잘라서 숫자로 바꾸어준 후 벡터에 값을 반영할 것이다.
  • 벡터가 다 채워졌으면, 이제 왼쪽 상단 꼭지점을 기준으로, 배열을 순회할 것이다.
    => 무슨말이냐 하면, 배열의 각 점을 정사각형의 왼쪽 상단 꼭지점으로 생각하고, 정사각형을 찾아보는 것이다.
  • 그런데, 입력을 받을 때 행과 열의 크기를 받았다. 정사각형은 가로와 세로의 길이가 같아야 하기 때문에 행과 열 중에서 더 작은 값이 정사각형의 최대 길이가 될 수 있다.
  • 따라서 행과 열 중 최소의 길이가 1이었다면, 최대 정사각형 길이는 1이기 때문에 크기가 1이다. 
  • 그리고 행과 열 중 최소의 길이가 1이 아니라면 그 값을 m에 저장해 두고, 다음 절차를 통해 최대 길이를 찾아낼 수 있다.
  • 먼저 정사각형의 한변의 길이가 2인 것부터 찾아볼 것이다.
  • 현재 왼쪽 상단 꼭지점의 위치를 (i,j)라고 할 때 길이가 2인 정사각형의 꼭짓점은 (i+1, j) (i,j+1), (i+1, j+1)이 된다.
  • 따라서 k가 1일 때부터 m보다 작을 때까지 정사각형을 키워가면서 조건을 만족하는지 보면 된다.
  • i+k<N이고, j+k<M이면, 해당 정사각형은 행렬안에 유효한 것이다. 따라서 이런 경우에는 (i,j)가 (i+1, j) (i,j+1), (i+1, j+1)각각과 값이 동일한지 비교해주면 된다. 
    => 값이 동일하면, answer의 기존 값과 비교해서 더 큰 값으로 answer를 갱신해주면된다.
  • 참고로 answer는 행렬을 순회하기 전에 1로 초기화 하여 생성해두어야 한다.
  • 모든 순회가 끝난 후 최종 answer값을 제곱한 값을 출력해주면 된다. (문제에서 정사각형의 크기를반환하라고 하였기 때문이다.)

 

전체 코드는 아래와 같다.

#include<iostream>
#include<algorithm>
#include<string>
#include<vector>

using namespace std;

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int N, M;
	cin >> N >> M;

	int m = min(N, M);//작은 값이 정사각형의 한 변의 max가 됨

	vector<vector<int>> rec(N, vector<int>(M, 0));

	for (int i = 0; i < N; i++) {
		string str;
		cin >> str;

		for (int j = 0; j < str.length(); j++) {
			rec[i][j] = str[j]-'0'; //char 문자를 숫자로 바꾸는 함수는 atoi를 쓰지만, string으로 되어 있는 경우엔 인자가 맞지 않으므로,'0'을 뻬주어서 구한다.
		}
	}

	if (m == 1) {
		cout << 1;
		return 0;
	}

	int answer = 1;

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			for (int k = 1; k < m; k++) {
				if (i + k < N && j + k < M) {//사각형이 범위에 들어오는지 확인
					int t = rec[i][j];//기준이 되는 값을 저장
					if (rec[i][j + k] == t && rec[i + k][j] == t && rec[i + k][j + k] == t) {
						answer = max(k + 1, answer);
					}
				}
			}
		}
	}

	cout << answer * answer;//크기는 변의 제곱

	return 0;
}

 


✏ c++ 문법 알고 넘어가기!
  • 2차원 벡터 선언하기 : vector<vector<int>> vec(행크기, vector<int>(열크기, 초기값));
  • string의 각 문자를 숫자로 변환 : string의 각 문자를 변환할 때는 그냥 str[i]-'0'을 해주면 숫자 값을 얻을 수 있다.
    만약 char로 선언된 문자라면, atoi(문자) 메서드를 사용하면 된다.
    => string의 한 문자를 위 메서드 쓸 수 없는 이유는 인자 형태가 맞지 않아서이다.
반응형

+ Recent posts