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

 

16937번: 두 스티커

첫째 줄에 모눈종이의 크기 H, W, 둘째 줄에 스티커의 수 N이 주어진다. 다음 N개의 줄에는 스티커의 크기 Ri, Ci가 주어진다.

www.acmicpc.net

문제풀이

완전탐색 문제  + DFS + 아이디어 가 사용된 문제입니다.

 

문제푸는 방식입니다.

1. 문제를 보면 주어진 스티커를 90도로 회전하는 경우가 있습니다. 이를 고려하여 처음부터 스티커를 Node에 같이 넣어줍니다. 이떄 스티커 값을 넣을떄 주어진 그대로의 정보(Ri, Ci, 스티커 Index) 를 넣고, 90도 회전한 정보에 (Ci, Ri, 스티커 Index)를 넣습니다. 이떄 스티커 Index를 넣어주어야 이후에 완전탐색을 통해 모든 경우를 조사할때 같은 스티커를 같이 검사하지 않습니다.

2. 주어진 스티커 중 최대 2개의 스티커만 뽑아서 최대의 넓이를 구하기 위해 DFS를 활용하여 완전탐색을 진행합니다. 이 과정에서 1번과정에서 넣어준 StickerIndex를 사용하여 방문처리하여, 같은 스티커를 2번 뽑아서 사용하는 일이 없도록 합니다. 또한 선택된 스티커는 SelectedSticker[level]을 활용하여 SelectedSticker[0], SelectedSticker[1] 로써 관리합니다.

3. 만약 Level == 2 라면, 최대길이를 구하기 위해 

         3.1 가로로 배치한경우 ( 가로길이는 W보다 작거나 같고, 세로길이는 두개의 SelectedSticker[0], SelectedSticker[1] 중 최대의 높이만 H 보다 작거나 같으면 됩니다. ) 그리고서 스티커의 넓이는 구해서 더합니다.

         3.2 세로로 배치한경우 ( 세로길이는 H보다 작거나 같고, rkfh길이는 두개의 SelectedSticker[0], SelectedSticker[1] 중 최대의 가로만 W 보다 작거나 같으면 됩니다. ) 그리고서 스티커의 넓이는 구해서 더합니다.

 

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static int H, W;
public static int N;
public static ArrayList<Node> Node = new ArrayList<Node>();
public static boolean[] visited;
public static Node[] SelectedSticker = new Node[2]; //2개의 선택된 스티커 사용
public static int result = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
H = Integer.parseInt(st.nextToken());
W = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
visited = new boolean[N];
for(int i=0;i<N;i++) {
st = new StringTokenizer(br.readLine());
int R = Integer.parseInt(st.nextToken());
int C = Integer.parseInt(st.nextToken());
Node.add(new Node(R, C, i));
if( R != C) { //90도 회전까지 넣습니다.
Node.add(new Node(C, R, i));
}
}
simulate(0, 0);
System.out.println(result);
}
public static void simulate(int idx, int level) {
if(level == 2) {
//가로로 배치할때 ( 세로길이는 Sticker중 가장 긴것만 고려합니다. )
if(SelectedSticker[0].c + SelectedSticker[1].c <= W && Math.max(SelectedSticker[0].r, SelectedSticker[1].r) <= H) {
result = Math.max(result, SelectedSticker[0].r * SelectedSticker[0].c + SelectedSticker[1].r * SelectedSticker[1].c);
}
//세로로 배치할때 ( 가로길이는 Sticker중 가장 긴것만 고려합니다. )
if(SelectedSticker[0].r + SelectedSticker[1].r <= H && Math.max(SelectedSticker[0].c, SelectedSticker[1].c) <= W) {
result = Math.max(result, SelectedSticker[0].r * SelectedSticker[0].c + SelectedSticker[1].r * SelectedSticker[1].c);
}
return ;
}
for(int i=idx;i<Node.size();i++) {
Node temp = Node.get(i);
int R = temp.r;
int W = temp.c;
int TEMPSTICKERINDEX = temp.stickerIndex;
if(visited[TEMPSTICKERINDEX] == true) continue; //중복된 스티커가 사용되지 않도록 처리합니다.
visited[TEMPSTICKERINDEX] = true;
SelectedSticker[level] = temp; //Sticker의 순서에 맞춰 넣습니다.
simulate(i + 1,level + 1);
SelectedSticker[level] = null; //Sticker를 사용햇다면 제거합니다.
visited[TEMPSTICKERINDEX] = false;
}
}
}
class Node{
int r;
int c;
int stickerIndex;
public Node(int r, int c, int stickerIndex) {
this.r = r;
this.c = c;
this.stickerIndex = stickerIndex;
}
}

+ Recent posts