일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 수영대회결승전
- ARM
- ros
- 삼성기출
- 구현
- 포탑부수기
- 3Dreconstruction
- 토끼와 경주
- 소프티어
- 싸움땅
- 슈퍼컴퓨터클러스터
- DP
- 마법의숲탐색
- Calibration
- 이진탐색
- 순서대로방문하기
- 마이크로프로세서
- 코드트리
- ICER
- 왕실의기사대결
- BFS
- DenseDepth
- dfs
- 시뮬레이션
- 코드트리빵
- 나무박멸
- 루돌프의반란
- ISER
- 백준
- 조합
Archives
- Today
- Total
from palette import colorful_colors
[백준] 14502 연구소 with C++ (삼성기출) 본문
https://www.acmicpc.net/problem/14502
언어: C++, 시간: 52ms
2차원 격자에서 조합을 이용한 대표적인 문제.
사실 조합을 안 쓰고 그냥 순열로 벽을 세우는걸 생각해도 된다. 하지만 그러면 굉장히 느려진다.
(나의 경우 52ms -> 332ms)
DFS를 통해서 벽을 세우고, 벽을 다 세우면 BFS를 이용해서 바이러스 퍼뜨렸다.
꼭 복습하기!
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
int MAP[9][9];
int N, M;
int emptyCnt;
int answer = 0;
int dy[4] = { -1, 1, 0, 0 };
int dx[4] = { 0, 0, -1, 1 };
struct Node {
int y;
int x;
};
vector <Node> startPoints;
void input() {
cin >> N >> M;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
cin >> MAP[i][j];
if (MAP[i][j] == 0)
emptyCnt++;
else if (MAP[i][j] == 2) {
startPoints.push_back({ i, j });
}
}
}
emptyCnt = emptyCnt - 3; // 짜피 벽 3개 세울꺼니깐
}
// BFS로 바이러스 퍼뜨리기
void spread() {
int curEmptyCnt = emptyCnt;
for (auto startPoint : startPoints) {
queue <Node> q;
q.push({ startPoint.y, startPoint.x });
while (!q.empty()) {
Node now = q.front();
q.pop();
for (int k = 0; k < 4; k++)
{
int ny = now.y + dy[k];
int nx = now.x + dx[k];
if (ny < 0 || nx < 0 || ny >= N || nx >= M)
continue;
if (MAP[ny][nx] != 0)
continue;
MAP[ny][nx] = 2;
curEmptyCnt--;
q.push({ ny, nx });
}
}
}
answer = max(answer, curEmptyCnt);
}
void func(int level, int preRow, int preCol) {
// 종료조건
if (level == 3) {
int backupMAP[9][9];
memcpy(backupMAP, MAP, sizeof(MAP));
spread();
memcpy(MAP, backupMAP, sizeof(MAP));
return;
}
// 탐색
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
if (MAP[i][j] != 0)
continue;
///////////////// 아래의 두 if문을 주석처리해도 코드는 잘 돌아간다.
// 아래의 문장을 주석처리하면 순열이고, 순열은 조합을 포함하기 때문.
// 하지만 코딩테스트에 시간초과를 대비하기 위해 꼭 조합 쓰는 방법 익히기!!!
if (level > 0 && i < preRow)
continue;
if (level > 0 && i == preRow && j <= preCol)
continue;
//////////////////
MAP[i][j] = 1;
func(level + 1, i, j);
MAP[i][j] = 0;
}
}
}
int main() {
//freopen("sample_input.txt", "r", stdin);
input();
func(0, 0, 0);
cout << answer;
return 0;
}
'알고리즘 > 문제풀이' 카테고리의 다른 글
[Softeer] 순서대로 방문하기 with C++ (HSAT 7회 기출) (0) | 2024.04.01 |
---|---|
[백준] 15684 사다리조작 with C++ (삼성기출) (0) | 2024.04.01 |
[백준] 15683 감시 with C++ (삼성기출) (0) | 2024.03.31 |
[SWEA] 1949 등산로 조성 with C++ (0) | 2024.03.03 |
[SWEA] 3234 준환이의 양팔저울 with C++ (0) | 2024.03.03 |