danbibibi
article thumbnail

문제

문제 바로가기> BOJ 15684번: 사다리 조작

 

15684번: 사다리 조작

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

www.acmicpc.net

 

풀이

 

** 시간 초과 방지를 위한 Tip **

1. h번 가로선에서 사다리를 조작한 경우, 그 다음 조작할 사다리는 h번 가로선 부터 찾아가면 된다.

  → 이미 앞에서 계산했으므로 ! (이 부분이 중요 )

 

2. 가로선을 연속해서 나란히 놓을 필요가 없기 때문에,

`isLine[a][b] || isLine[a][b+1] || isLine[a][b-1]` 다음 중 하나라도 해당 된다면, 가로선을 놓을 필요가 없다.

 

3. maxcnt(최대 놓을 수 있는 사다리 개수)를 0에서 3까지 순차적으로 설정해주고 탐색을 진행한다.

  → 탐색을 진행하다 ans 값이 갱신된다면, 더 이상 탐색을 진행할 필요가 없다!

 

C++

#include<iostream>
#include<vector>
#define MAX_H 31
#define MAX_N 11
#define IMPOSSIBLE 4
using namespace std;

int N, M, H;
int ans = IMPOSSIBLE;
bool isLine[MAX_H][MAX_N];

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

	int a, b;
	for (int i = 0; i < M; i++) {
		cin >> a >> b; // 1 ≤ a ≤ H , 1 ≤ b ≤ N-1
		isLine[a][b] = true; // 입력으로 주어지는 가로선이 서로 연속하는 경우는 없음
	}
}

bool ispossible() {
	for (int n = 1; n <= N; n++) { // 세로선
		int col = n;
		for (int h = 1; h <= H; h++) {
			if (isLine[h][col]) col++;
			else if (isLine[h][col - 1]) col--;
		}
		if (col != n) return false; // i번 세로선의 결과 != i번
	} return true;
}

void solution(int cnt, int row, int maxcnt) {
    if(cnt == maxcnt){
        if(ispossible()) ans = maxcnt; // i번 세로선의 결과가 i번이 나오도록 사다리 게임을 조작하려면, 추가해야 하는 가로선 개수의 최솟값
        return;
    }
    for (int a = row; a <= H; a++) {
		for (int b = 1; b < N; b++) {
			if (isLine[a][b] || isLine[a][b+1] || isLine[a][b-1]) continue; // 이미 가로선이 있는 경우, 서로 연속하는 경우
			isLine[a][b] = true;
			solution(cnt + 1, a, maxcnt);
			isLine[a][b] = false;
		}
	}
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    input();
    for(int maxcnt=0; maxcnt<4 && ans==IMPOSSIBLE; maxcnt++) solution(0, 1, maxcnt);
    ans == IMPOSSIBLE ? cout << -1 : cout << ans;
}

 

Java

import java.io.*;
import java.util.*;

public class Main {
	
	static final int IMPOSSIBLE = 4;
	static int ans = IMPOSSIBLE;
	
	static int N, M, H;
	static boolean[][] isLine;
	
	
	public static void main(String[] args) throws Exception {
		// System.setIn(new FileInputStream("res/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		H = Integer.parseInt(st.nextToken());
		isLine = new boolean[H+1][N+1];
		
		int a, b;
		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			a = Integer.parseInt(st.nextToken());
			b = Integer.parseInt(st.nextToken());
			isLine[a][b] = true; // 입력으로 주어지는 가로선이 서로 연속하는 경우는 없음
		}
		
	    for(int maxcnt=0; maxcnt<4 && ans==IMPOSSIBLE; maxcnt++) solution(0, 1, maxcnt);
	    if(ans == IMPOSSIBLE) System.out.println(-1);
	    else System.out.println(ans);
		
	}
	
	static void solution(int cnt, int row, int maxcnt) {
	    if(cnt == maxcnt){
	        if(ispossible()) ans = maxcnt; // i번 세로선의 결과가 i번이 나오도록 사다리 게임을 조작하려면, 추가해야 하는 가로선 개수의 최솟값
	        return;
	    }
	    for (int a = row; a <= H; a++) {
			for (int b = 1; b < N; b++) {
				if (isLine[a][b] || isLine[a][b+1] || isLine[a][b-1]) continue; // 이미 가로선이 있는 경우, 서로 연속하는 경우
				isLine[a][b] = true;
				solution(cnt + 1, a, maxcnt);
				isLine[a][b] = false;
			}
		}
	}
	
	static boolean ispossible() {
		for (int n = 1; n <= N; n++) { // 세로선
			int col = n;
			for (int h = 1; h <= H; h++) {
				if (isLine[h][col]) col++;
				else if (isLine[h][col - 1]) col--;
			}
			if (col != n) return false; // i번 세로선의 결과 != i번
		} return true;
	}
}

 

'문제 풀이 > SW 역량 테스트' 카테고리의 다른 글

BOJ 12100번: 2048 (Easy)  (0) 2023.02.18
BOJ 17837번: 새로운 게임 2  (0) 2023.02.08
BOJ 17779번: 게리맨더링 2  (0) 2023.02.04
BOJ 17140번: 이차원 배열과 연산  (0) 2023.02.02
BOJ 17142번: 연구소 3  (0) 2023.02.01
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로