developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 삼성코테파이썬
  • 카카오코테
  • c++ 빌더 패턴
  • BOJ파이썬풀이
  • 시계열
  • AR모형
  • 시계열분석
  • 통계분석
  • 카카오코테java풀이
  • 삼성코테파이썬풀이
  • 삼성코테기출자바풀이
  • c++디자인패턴
  • 데이터분석
  • 삼성코테기출
  • Arima
  • ARIMA모형
  • 삼성코테자바준비
  • 삼성코테자바꿀팁
  • SW역량테스트파이썬풀이
  • 백준파이썬풀이
  • 삼성코테준비
  • 삼성코테파이썬준비
  • 삼성코테구현풀이
  • 운영체제인터럽트
  • 코테파이썬
  • MA모형
  • 삼성코테자바풀이
  • 통계학
  • SW역량테스트파이썬
  • 삼성코테구현문제추천

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

BOJ - 게리맨더링2 17779번 (python, JAVA)

2021. 10. 17. 23:41

❓ 문제 - 백준 게리맨더링2 17779번 - python, JAVA 풀이법

 

출처 

(https://www.acmicpc.net/problem/17779)

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름

www.acmicpc.net

 

 

📝 문제해결법

1. 이 문제는 구현으로 풀었다.

  • 재현시의 격자의 각 칸에 해당하는 인구수의 정보를 입력받고, total 변수에 총 인구수를 저장한다.
  • 일단 문제에서 주어진 기준점(x,y)와 경계의 길이(d1, d2)의 범위 안에서 해당하는 수를 조건에 맞춰서 다섯 개의 선거구로 나눈 후 선거구의 차이가 가장 작은 수를 계속 갱신하면서 정답을 출력한다.
  • 기준점(x, y)와 경계의 길이(d1, d2)의 범위는 (d1, d2 ≥ 1, 1 ≤ x < x+d1+d2 ≤ N, 1 ≤ y-d1 < y < y+d2 ≤ N) 이므로 4중 포문(1 ~ n+1) 돌면서 x+d1+d2 > n, y-d1 < 1, y + d2 > n의 경우는 범위를 벗어나므로 선거구의 인구수 차이를 계산하지 않고 나머지 경우엔 선거구의 인구수 차이를 계산한다.
  • x, y, d1, d2에서 선거구를 나눌 땐, 일단 경계선을 만들어야 하는데 경계선을 만들 때 조건은 문제에서 주어진 2번 조건으로 5번 선거구의 경계선을 표시한다.
  • 그 다음은 1 ~ 4번 선거구를 찾기 위해 문제 4번에서 주어진 조건의 범위를 이용하여 1 ~ 4번 선거구를 표시한다. 해당 선거구의 지역을 구하기 위해서 선거구의 조건의 범위 안에 들 때, 해당 칸의 인구수를 더해준다. 만약 해당 범위를 돌면서 5번 즉, 경계선을 만나면 인구수를 더해주지 않고 break를 해준다.
  • 1, 3 선거구는 열에서 오른쪽으로 가면서 해당 범위에 해당되는지 파악한 후 인구수를 더해주며 경계선을 만나면 다음 행에 대해 파악한다. 2, 4 선거구는 열은 왼쪽으로 가면서 해당 범위에 해당되는지 파악하며 인구수를 더해주며 만약 경계선을 만나면 다음 행에 대해 파악한다.
  • 전체 인구 수(total) 에서 구한 1,2,3,4 선거구의 인구수를 빼서 5 선거구의 인구수를 구한다.
  • 5개의 선거구에서 최대 인구수의 선거구와 최소 인구수의 선거구를 빼서 최소 인구수의 차이를 갱신하며 구한다.

 

 

💻 소스코드 (python)

n = int(input())
graph = [[0 for _ in range(n+1)]]
total = 0

for i in range(n):
    data = [0] + list(map(int, input().split()))
    total += sum(data)
    graph.append(data)

min_diff = int(1e9)

def solve(x, y, d1, d2):
    global min_diff
    g = [[0]*(n+1) for _ in range(n+1)]
    people = [0, 0, 0, 0, 0]
    # 경계선 그리기
    g[x][y] = 5
    for i in range(1, d1+1):
        g[x+i][y-i] = 5
    for i in range(1, d2+1):
        g[x+i][y+i] = 5
    for i in range(1, d2+1):
        g[x+d1+i][y-d1+i] = 5
    for i in range(1, d1+1):
        g[x+d2+i][y+d2-i] = 5


    # 1
    for i in range(1, x+d1):
        for j in range(1, y+1):
            if g[i][j] == 5:
                break
            else:
                people[0] += graph[i][j]

    # 2
    for i in range(1, x+d2+1):
        for j in range(n, y, -1):
            if g[i][j] == 5:
                break
            else:
                people[1] += graph[i][j]

    # 3
    for i in range(x+d1, n+1):
        for j in range(1, y-d1+d2):
            if g[i][j] == 5:
                break
            else:
                people[2] += graph[i][j]
    # 4
    for i in range(x+d2+1, n+1):
        for j in range(n, y-d1+d2-1, -1):
            if g[i][j] == 5:
                break
            else:
                people[3] += graph[i][j]

    people[4] = total - sum(people[0:4])
    min_diff = min(min_diff, max(people)-min(people))

for x in range(1, n+1):
    for y in range(1, n+1):
        for d1 in range(1, n+1):
            for d2 in range(1, n+1):
                if x+d1+d2 > n:
                    continue
                if y-d1 < 1:
                    continue
                if y + d2 > n:
                    continue
                solve(x, y, d1, d2)

print(min_diff)

 

 

💻 소스코드 (JAVA)

// BOJ - 게리멘더링2(17779번)
// 구현

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main_17779 {
	public static int[][] map;
	public static int n, total, ans;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		n = Integer.parseInt(br.readLine());
		map = new int[n+1][n+1];
		for(int i=1;i<=n;i++) {
			String[] data = br.readLine().split(" ");
			for(int j=1;j<=n;j++) {
				map[i][j] = Integer.parseInt(data[j-1]);
				total += map[i][j];
			}
		}
		ans = Integer.MAX_VALUE;
		for(int x=1;x<=n;x++) {
			for(int y=1;y<=n;y++) {
				for(int d1=1;d1<=n;d1++) {
					for(int d2=1;d2<=n;d2++) {
						if(x+d1+d2 > n) continue;
						if(y-d1 < 1) continue;
						if(y+d2 > n) continue;
						solve(x, y, d1, d2);
					}
				}
			}
		}
		System.out.println(ans);


	}

	public static void solve(int x, int y, int d1, int d2) {
		int[][] map2 = new int[n+1][n+1];
		int[] people = new int[5];

		// 경계선 그리기
		map2[x][y] = 5;
		for(int i=1;i<=d1;i++) {
			map2[x+i][y-i] = 5;
		}

		for(int i=1;i<=d2;i++) {
			map2[x+i][y+i] = 5;

		}

		for(int i=1;i<=d2;i++) {
			map2[x+d1+i][y-d1+i] = 5;
		}

		for(int i=1;i<=d1;i++) {
			map2[x+d2+i][y+d2-i] = 5;
		}

		// 1선거구
		for(int i=1;i<x+d1;i++) {
			for(int j=1;j<=y;j++) {
				if(map2[i][j] == 5) break;
				people[0] += map[i][j];
			}
		}

		// 2선거구
		for(int i=1;i<=x+d2;i++) {
			for(int j=n;j>y;j--) {
				if(map2[i][j] == 5) break;
				people[1] += map[i][j];
			}
		}

		// 3선거구
		for(int i=x+d1;i<=n;i++) {
			for(int j=1;j<y-d1+d2;j++) {
				if(map2[i][j] == 5) break;
				people[2] += map[i][j];
			}
		}

		// 4선거구
		for(int i=x+d2+1;i<=n;i++) {
			for(int j=n;j>=y-d1+d2;j--) {
				if(map2[i][j] == 5) break;
				people[3] += map[i][j];
			}
		}

		people[4] = total - (people[0] + people[1] + people[2] + people[3]);
		int min = Integer.MAX_VALUE;
		int max = 0;
		for(int i=0;i<5;i++) {
			max = Math.max(max, people[i]);
			min = Math.min(min, people[i]);
		}

		ans = Math.min(ans, max-min);


	}



	}

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

BOJ - 원판 돌리기 17822번 (python)  (0) 2021.10.18
BOJ - 새로운 게임2 17837번 (python)  (0) 2021.10.18
BOJ - 연구소 3 17142번 (python)  (0) 2021.10.17
BOJ - 이차원 배열과 연산 17140번 (python)  (0) 2021.10.17
BOJ - 낚시왕 17143번 (python)  (0) 2021.10.17
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 원판 돌리기 17822번 (python)
    • BOJ - 새로운 게임2 17837번 (python)
    • BOJ - 연구소 3 17142번 (python)
    • BOJ - 이차원 배열과 연산 17140번 (python)
    developer-ellen
    developer-ellen

    티스토리툴바