Baekjun-2304号(倉庫ポリゴン)


質問元:https://www.acmicpc.net/problem/2304
質問する

  • N本の柱が一列に並んでいます.柱の幅はすべて1メートルで、高さは違うかもしれません.これらの柱で鉄皮倉庫を作ります.倉庫にはすべての柱が入っています.この倉庫の屋根は次のように作られています.
  • 屋根は水平部分と垂直部分で構成されており、接続されています.
  • 屋根の水平部分は、ある柱の頂面に接しなければならない.
  • 屋根の垂直部分は、ある柱の側面に接しなければならない.
  • 屋根の縁は着地します.
  • 雨が降った場合、水たまりを防ぐため、屋根のどの部分も凹むことはできません.

  • 図1は倉庫がそばにある原形を描いている.この図の太い線で示された部分は屋根に相当し、屋根と地面に囲まれた多角形がそばに倉庫が見えた.この多角形を倉庫多角形と呼びましょう.

  • 図1.柱の例

  • 倉庫のボスは、倉庫の多角形面積が最も小さい倉庫を構築したいと思っています.図1の倉庫多角形の面積は98平方メートルであり、この場合は最小の倉庫多角形である.

  • 柱の位置と高さを指定する場合は、最小倉庫の多角形面積を求めるプログラムを作成します.
  • import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.*;
    
    public class Main {
    
        private static class Pole implements Comparable<Pole> {
    
            int x;
            int y;
    
            public Pole(int x, int y) {
                this.x = x;
                this.y = y;
            }
    
            @Override
            public int compareTo(Pole o) {
                return this.x - o.x;
            }
    
        }
    
        public static void main(String[] args) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            int N = Integer.parseInt(reader.readLine()); // 기둥의 개수
    
            List<Pole> poleList = new ArrayList<>();
    
            for (int i = 0; i < N; i++) {
                StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
                int x = Integer.parseInt(tokenizer.nextToken());
                int y = Integer.parseInt(tokenizer.nextToken());
                poleList.add(new Pole(x, y));
            }
    
            Collections.sort(poleList);
    
            int maxY = 0; // 가장 높은 기둥
            int index = 0; // 가장 높은 기둥의 인덱스
    
            // 가장 높은 기둥 찾기
            for (int i = 0, size = poleList.size(); i < size; i++) {
                if (poleList.get(i).y > maxY) {
                    maxY = poleList.get(i).y;
                    index = i;
                }
            }
    
            int area = 0; // 넓이를 저장하는 변수
    
            int leftY = poleList.get(0).y; // 왼쪽 끝 기둥
            int leftX = poleList.get(0).x; // x 좌표 위치
    
            for (int i = 1; i <= index; i++) {
                if (leftY <= poleList.get(i).y) {
                    area += leftY * (poleList.get(i).x - leftX);
                    leftY = poleList.get(i).y;
                    leftX = poleList.get(i).x;
                }
            }
    
            int rightY = poleList.get(poleList.size() - 1).y; // 오른쪽 끝 기둥
            int rightX = poleList.get(poleList.size() - 1).x; // x 좌표 위치
    
            for (int i = poleList.size() - 2; i >= index; i--) {
                if (rightY <= poleList.get(i).y) {
                    area += rightY * (rightX - poleList.get(i).x);
                    rightY = poleList.get(i).y;
                    rightX = poleList.get(i).x;
                }
            }
    
            area += maxY;
    
            System.out.println(area);
        }
    
    }
    
  • 各カラムのx座標と高さ情報を格納するクラスを作成します.
  • の各支柱情報を格納するリストを生成し、x座標を基準としてリストをソートする.
  • の最高柱の情報を取得します.この柱は屋根の左右の仕切りになっている.
  • で最も高い柱を求め、左から柱までの幅、そして右から柱までの幅、2つを合わせて、残りの最大柱の高さ、最終的な幅を完成します.
  • 程度の屋根の探索を行う際には,<=演算を用いて同じ高さの柱を扱う場合もある.