인프런 커뮤니티 질문&답변

yeon _leaf님의 프로필 이미지
yeon _leaf

작성한 질문수

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

3-K와 문제의 단순화

3-K 질문입니다.

해결된 질문

작성

·

182

0

http://boj.kr/41c7ab64738e4a22a04e301a8a8111ec

플러드필을 사용해서 얼음 녹이기 -> 백조 움직이기를 반복하는 로직입니다. 얼음에 큐 2개, 백조에 큐 2개를 사용했습니다.

시간 초과가 어디서 발생하는지 모르겠습니다. 제가 놓친 부분이 어디인지 궁금합니다.

답변 1

1

큰돌님의 프로필 이미지
큰돌
지식공유자

한개 빼고는 잘 짜셨습니다.ㅎㅎ 백조의 호수는 좀 타이트해서 맞는 코드인데도 시간초과가 발생하기도 해요. 제가 해답코드로 제시한 코드 조차도 몇개 코드만 좀 수정하면 (맞는 로직인데도) 시간초과가 발생합니다.

그냥 이런 문제는 이런 거구나 하고 넘기시면 될 거같아요. 또한 yeon님 코드 피드백 드렸으니 참고부탁드려요.

#include <bits/stdc++.h>
using namespace std;
//good 근데 이거 범위가 1500이라서 2000을 줘도 되요. 
const int base = 2253001;
int r, c;
char board[1501][1501];
int v1[1501][1501];
int v2[1501][1501]; 
int si, sj;
queue<int> water;
queue<int> swan;
int days;

int di[] = {-1, 0, 1, 0};
int dj[] = {0, 1, 0, -1};


void melting() {
	queue<int> tmp1;
	// good
	while (water.size()) {
		int cl = water.front(); water.pop();
		int ci = cl / base;
		int cj = cl % base;
		for (int d=0; d<4; d++) {
			int ni = ci + di[d];
			int nj = cj + dj[d];
			if (ni < 0 || nj < 0 || ni >= r || nj >= c || v1[ni][nj] || board[ni][nj] == 'L') continue;
			if (board[ni][nj] == 'X') {
				v1[ni][nj] = 1;
				board[ni][nj] = '.';
				tmp1.push(base * ni + nj);
				continue;
			}
			v1[ni][nj] = 1;
			water.push(base * ni + nj);
		}
	}
	water = tmp1;
}

bool move_swan() {
	queue<int> tmp2;
	bool flag = 0;
	while (swan.size()) {
		int cl = swan.front(); swan.pop();
		int ci = cl / base;
		int cj = cl % base;
		// good
		for (int d=0; d<4; d++) {
			int ni = ci + di[d];
			int nj = cj + dj[d];
			if (ni < 0 || nj < 0 || ni >= r || nj >= c || v2[ni][nj]) continue;
			//good
			if (board[ni][nj] == 'L') {
				flag = 1;
				break;
			}
			if (board[ni][nj] == 'X') {
				v2[ni][nj] = 1;
				tmp2.push(base * ni + nj);
				continue; 
			}
			v2[ni][nj] = 1;
			swan.push(base * ni + nj);
		}
		if (flag) break;
	}
	swan = tmp2;
	return flag;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	
	cin >> r >> c;
	
	for (int i=0; i<r; i++) {
		string line;
		cin >> line;
		for (int j=0; j<c; j++) {
			board[i][j] = line[j];
			//백조여도 물에다 푸시해줘야해요. 백조는 물위에 떠있는거니까요. 
			if (board[i][j] == 'L') {
				si = i; sj = j;
			}
			
			if (board[i][j] == '.') {
				v1[i][j] = 1;
				water.push(base*i + j);
			}
		}
	}
	
	swan.push(base * si + sj);
	v2[si][sj] = 1;
	
	while (true) {
		bool test = move_swan();
        if (test) break;
		melting();
		days++;
	}
	
	cout << days << "\n";
	
	return 0;
}
큰돌님의 프로필 이미지
큰돌
지식공유자

아 그리고 2253001 가 base인데

문제의 범위는 1500

최대치는 3,379,501,500 인데 이거 int 범위 벗어나네요.

yeon _leaf님의 프로필 이미지
yeon _leaf
질문자

아 queue 내부에서 base i + j 식을 사용하기 때문에 최대치는 base가 아니라 base * i가 되는군요. 그 부분을 생각하지 못했습니다. 그러면 long long 자료형을 사용하거나 그냥 pair<int, int>형을 사용해야겠네요. 답변 감사합니다!!

yeon _leaf님의 프로필 이미지
yeon _leaf

작성한 질문수

질문하기