Study/Coding Test

[백준] 사다리 조작

_gayeon 2021. 10. 21. 21:26

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

 

15684번: 사다리 조작

사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선

www.acmicpc.net

 

시간 초과 발생.

dfs를 돌 때마다 r이 1부터 돌아서 문제였다. idx를 저장해두고, 그 idx부터 for문 돌리니까 통과.

bool findPos(int idx, int cnt, int curr) {
	if (cnt == curr) {
		if (check()) {
			//print();
			return true;
		}
		return false;
	}
	for (int r = idx; r <= H; r++) {
		for (int c = 1; c < N; c++) {

...
				if (flag) {
					bool result = findPos(r, cnt, curr + 1);
					if (result) {
						return true;
					}
					board[r][c] = 0;
				}
			}
		}
	}
	return false;
}

 

전체 코드

#define _CRT_SECURE_NO_DEPRECATE

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

int answer;
int N, M, H;
vector< vector<int>> lines; // {가로선, 세로선}
int board[32][12];

void init() {

}

void input() {
	cin >> N >> M >> H;

	for (int i = 0; i < M; i++) {
		int a, b;
		cin >> a >> b;
		lines.push_back({ a,b });
		board[a][b] = 1;
	}
}

bool inRange(int r, int c) {
	return r >= 1 && r <= H && c >= 1 && c <= N;
}

void print() {
	for (int r = 1; r <= H; r++) {
		for (int c = 1; c <= N; c++) {
			cout << board[r][c] << " ";
		}
		cout << endl;
	}
	cout << endl;
}

bool check(){
	for (int c = 1; c <= N; c++) {
		int idx = c;
		for (int r = 1; r <= H; r++) {
			if (board[r][idx] == 1) {
				idx = idx + 1;
			}
			else if (idx-1>=1 && board[r][idx-1] == 1) {
				idx = idx - 1;
			}
			//cout << idx << endl;
		}
		if (idx != c) {
			return false;
		}
	}
	return true;
}

bool findPos(int idx, int cnt, int curr) {
	if (cnt == curr) {
		if (check()) {
			//print();
			return true;
		}
		return false;
	}
	for (int r = idx; r <= H; r++) {
		for (int c = 1; c < N; c++) {
			if (board[r][c] == 0) {
				bool flag = false; // 가로선을 놓았는지
				if (c - 1 < 1) {
					if (board[r][c + 1] == 0) {
						board[r][c] = 1;
						flag = true;
					}
				}
				else if (c + 1 == N + 1) {
					if (board[r][c - 1] == 0) {
						board[r][c] = 1;
						flag = true;
					}
				}
				else {
					if (board[r][c - 1] == 0 && board[r][c + 1] == 0) {
						board[r][c] = 1;
						flag = true;
					}
				}

				if (flag) {
					bool result = findPos(r, cnt, curr + 1);
					if (result) {
						return true;
					}
					board[r][c] = 0;
				}
			}
		}
	}
	return false;
}

void solve() {
	if (check()) { //바로 통과하는 경우
		answer = 0;
		return;
	}
	for (int i = 1; i <= 3; i++) {
		if (findPos(1, i, 0)) {
			answer = i;
			return;
		}
	}

	answer = -1;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	//freopen("input.txt", "r", stdin);

	init();
	input();
	solve();

	cout << answer << endl;
	return 0;
}