Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Archives
Today
Total
관리 메뉴

최's 먹공로그

BOJ17779 게리맨더링2 본문

APS

BOJ17779 게리맨더링2

ChoiSH313 2022. 7. 24. 22:34

<Solution>

1. d1, d2, x, y로 지정 가능한 모든 경우를 본다. (일단 브루트포스)

2. 선거구를 나눈다.

(1) 경계선에 5 표시

(2) 경계선이 아닌 영역부터 bfs 돌면서 5 경계선 외부를 따로 표시

(3) 표시된 영역 제외하고 나머진 다 5

(4) 나머지 1~4 선거구는 규칙 따라서 표시

3. 최소값 을 구해준다

 

<Source Code>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class BOJ17779_게리멘더링2 {
	
	static int[][] map, visited;
	static int N;
	static int[] value_arr = new int[5];
	static int area_x1, area_x2, area_y1, area_y2;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		map = new int[N+1][N+1];
		visited = new int[N+1][N+1];
		int result = 9999999;
		for(int i = 1; i <= N; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j = 1; j <= N; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
				visited[i][j] = 0;
			}
		}
		for(int d1 = 1; d1 <= N; d1++) {
			for(int d2 = 1; d2 <= N; d2++) {
				for(int x = 1; x <= N; x++) {
					for(int y = 1; y <= N; y++) {
						// d1, d2 ≥ 1, 1 ≤ x < x+d1+d2 ≤ N, 1 ≤ y-d1 < y < y+d2 ≤ N)
						if((x < x+d1+d2) && (x+d1+d2 <= N) && (y > y - d1) && (y < y + d2) && (y-d1>=1) &&(y+d2<=N)) {
							// 경계선의 꼭지점을 기억(테두리 안에 들어오는 곳임을 알기위해)
							int[] area_y_arr = new int[5];
							area_y_arr[0] = y;
							area_y_arr[1] = y - d1;
							area_y_arr[2] = y + d2;
							area_y_arr[3] = y-d1+d2;
							area_y_arr[4] = y+d2-d1;
							Arrays.sort(area_y_arr);
							area_x1 = x;
							area_x2 = x + d1 + d2;
							area_y1 = area_y_arr[0];
							area_y2 = area_y_arr[4];
							
							// 선거구 나눠
							visited = new int[N+1][N+1];
							divide(d1, d2, x, y);
							System.out.print("======================");
							System.out.print(d1 + "," + d2 + "," + x + "," + y + "\n");
							for(int i = 1; i <= N; i++) {
								for(int j = 1; j <= N; j++) {
									System.out.print(visited[i][j] + " ");
								}
								System.out.print("\n");
							}
							// 최소값 구하기
							minvalue();
							System.out.print("value_arr : ");
							for(int i = 0; i < 5; i++)
								System.out.print(value_arr[i] + " ");
							System.out.print("\n");
							if(result > value_arr[4] - value_arr[0])
								result = value_arr[4] - value_arr[0];
							System.out.print("result : " + result + "\n");
						}
					}
				}
			}
		}
		System.out.print(result);
	}

	private static void minvalue() {
		value_arr = new int[5];
		for(int i = 1; i <= N; i++) {
			for(int j = 1; j <= N; j++) {
				if(visited[i][j] == 1)
					value_arr[0] += map[i][j];
				else if(visited[i][j] == 2)
					value_arr[1] += map[i][j];
				else if(visited[i][j] == 3)
					value_arr[2] += map[i][j];
				else if(visited[i][j] == 4)
					value_arr[3] += map[i][j];
				else if(visited[i][j] == 5)
					value_arr[4] += map[i][j];
			}
		}
		Arrays.sort(value_arr);
	}

	private static void divide(int d1, int d2, int x, int y) {
		// 경계선
		//(x, y), (x+1, y-1), ..., (x+d1, y-d1)
		//(x, y), (x+1, y+1), ..., (x+d2, y+d2)
		//(x+d1, y-d1), (x+d1+1, y-d1+1), ... (x+d1+d2, y-d1+d2)
		//(x+d2, y+d2), (x+d2+1, y+d2-1), ..., (x+d2+d1, y+d2-d1)
		for(int i = 0; i <= d1; i++) {
			if((x+i<=N) && (y-i>=1) && (y-i<=N))
				visited[x + i][y - i] = 5;
			if((x+d2+i<=N) && (y+d2-i<=N) && (y+d2-i)>=1)
				visited[x+d2+i][y+d2-i] = 5;
		}
		for(int i = 0; i <= d2; i++) {
			if((x+i<=N) && (y+i<=N))
				visited[x + i][y + i] = 5;
			if((x+d1+i<=N) && (y-d1+i<=N) && (y-d1+i>=1))
				visited[x+d1+i][y-d1+i] = 5;
		}
		// 나머지 선거구
		//1번 선거구: 1 ≤ r < x+d1, 1 ≤ c ≤ y
		//2번 선거구: 1 ≤ r ≤ x+d2, y < c ≤ N
		//3번 선거구: x+d1 ≤ r ≤ N, 1 ≤ c < y-d1+d2
		//4번 선거구: x+d2 < r ≤ N, y-d1+d2 ≤ c ≤ N
		for(int i = 1; i <= N; i++) {
			for(int j = 1; j <= N; j++) {
				// 1번
				if(i >= 1 && i < x + d1 && j >= 1 && j <= y && visited[i][j] != 5 && !((i > area_x1 && i < area_x2) && (j > area_y1 && j < area_y2))) {
					visited[i][j] = 1;
				}
				// 2번
				else if(i >= 1 && i <= x + d2 && j > y && j <= N && visited[i][j] != 5 && !((i > area_x1 && i < area_x2) && (j > area_y1 && j < area_y2))) {
					visited[i][j] = 2;
				}
				// 3번
				else if(i >= x + d1 && i <= N && j >= 1 && j < y-d1+d2 && visited[i][j] != 5 && !((i > area_x1 && i < area_x2) && (j > area_y1 && j < area_y2))) {
					visited[i][j] = 3;
				}
				// 4번
				else if(i > x + d2 && i <= N && j >= y-d1+d2 && j <= N && visited[i][j] != 5 && !((i > area_x1 && i < area_x2) && (j > area_y1 && j < area_y2))) {
					visited[i][j] = 4;
				}
				// 5번
				else
					visited[i][j] = 5;
			}
		}
	}
}

5의 테두리안에 들어온다는 건 x최소<x<x최대 & y최소<y<y최대 라는 거라서 해당 조건에 만족하면 5로 만들어 줬다... BFS를 사용하지 않고... 주어진 테케는 다 맞긴하지만 예외가 있는거 같은데... 모르겠음...

문제에서

선거구는 구역을 적어도 하나 포함해야 하고, 한 선거구에 포함되어 있는 구역은 모두 연결되어 있어야 한다. 구역 A에서 인접한 구역을 통해서 구역 B로 갈 수 있을 때, 두 구역은 연결되어 있다고 한다. 중간에 통하는 인접한 구역은 0개 이상이어야 하고, 모두 같은 선거구에 포함된 구역이어야 한다.

선거구는 구역을 적어도 하나 포함은 다 하는데 중간에 통하는 인전합 구역은 0개 이상이어야 하고?? 이게 뭔말인지 모르겠음

'APS' 카테고리의 다른 글

BOJ9441 Cash Cow  (1) 2022.10.08
BOJ18809 Gaaaaaaarden  (1) 2022.10.08
BOJ14503 로봇청소기  (0) 2022.06.26
BOJ9205 맥주 마시면서 걸어가기  (0) 2022.06.26
BOJ2573 빙산  (0) 2022.06.26