https://www.acmicpc.net/problem/1027
1027번: 고층 건물
세준시에는 고층 빌딩이 많다. 세준시의 서민 김지민은 가장 많은 고층 빌딩이 보이는 고층 빌딩을 찾으려고 한다. 빌딩은 총 N개가 있는데, 빌딩은 선분으로 나타낸다. i번째 빌딩 (1부터 시작)
www.acmicpc.net
문제
세준시에는 고층 빌딩이 많다. 세준시의 서민 김지민은 가장 많은 고층 빌딩이 보이는 고층 빌딩을 찾으려고 한다. 빌딩은 총 N개가 있는데, 빌딩은 선분으로 나타낸다. i번째 빌딩 (1부터 시작)은 (i,0)부터 (i,높이)의 선분으로 나타낼 수 있다. 고층 빌딩 A에서 다른 고층 빌딩 B가 볼 수 있는 빌딩이 되려면, 두 지붕을 잇는 선분이 A와 B를 제외한 다른 고층 빌딩을 지나거나 접하지 않아야 한다. 가장 많은 고층 빌딩이 보이는 빌딩을 구하고, 거기서 보이는 빌딩의 수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 빌딩의 수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에 1번 빌딩부터 그 높이가 주어진다. 높이는 1,000,000,000보다 작거나 같은 자연수이다
출력
첫째 줄에 문제의 정답을 출력한다.
풀이
각 빌딩 간의 선분을 전부 찾고, 해당 선분들 중 가장 많은 종단점이 위치한 빌딩을 찾으면 된다.
먼저 (i1, h1)에서 (i2, h2)로 가는 선분이 i1 초과 i2 미만 구간에 속한 빌딩과 접촉하는지 안하는지 판별한다.
해당 선분의 방정식은 이렇다.
이 방정식의 i자리에 판별하고 싶은 빌딩의 위치를 입력해주면 그에 해당하는 선분의 h값과 빌딩의 높이를 비교하면서 가장 많은 종단점이 위치한 빌딩을 찾는다.
소스코드
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//백준 1027번 고층빌딩 골드 4
namespace BaekJoon_1027
{
class Program
{
static void Main(string[] args)
{
//입력받기
int N = int.Parse(Console.ReadLine());
string[] raw_building = Console.ReadLine().Split(' ');
double[] building = new double[N];
for(int i = 0;i<N;i++)
building[i] = double.Parse(raw_building[i]);
//building의 인덱스가 i좌표, 해당 배열의 값이 높이라고 보면 된다.
Solution(building, Combination(N), N);
Console.ReadLine();
}
static List<int []> Combination(int N) {//주어진 수보다 작은 수들 2개씩 조합 뽑기(중복허용 X)
List<int []> Combinate = new List<int []>();
for (int i = 0; i < N; i++) {
for(int j = i+1;j<N;j++){
int [] a = {i, j};
Combinate.Add(a);
//Console.WriteLine(a[0] + ", "+ a[1]);
}
}
return Combinate;
}
static void Solution(double[] building, List<int[]> comb, int N)
{
int[] count = new int[N];
count.Initialize();
for (int i = 0; i < comb.Count; i++) {//각 조합마다 연산한다.
double y_dif = building[comb[i][1]] - building[comb[i][0]];
double x_dif = comb[i][1] - comb[i][0];
double vert = (building[comb[i][1]] - building[comb[i][0]]) / (comb[i][1] - comb[i][0]);//선분의 기울기.
double y_mt = building[comb[i][0]] - comb[i][0] * vert;//선분의 y절편
bool is_available = true;
for (int j = comb[i][0] + 1; j < comb[i][1]; j++) { //두 빌딩 사이에 있는 빌딩들이 선분과 만나는지 비교한다.
if (building[j] >= vert * j + y_mt) { //빌딩이 해당 선분과 만난다면
is_available = false;
break;
}
}
if (is_available)//유효한 선분이면
{
int[] a = { comb[i][0], comb[i][1] };
count[comb[i][0]]++;//두 빌딩의 볼 수 있는 빌딩 갯수를 1개씩 추가한다.
count[comb[i][1]]++;
}
}
Array.Sort(count);//count배열 정렬 후 가장 큰값 출력.
Console.WriteLine(count[N-1]);
return;
}
}
}
'Algorithm > BaekJoon' 카테고리의 다른 글
[백준] 파이썬 알고리즘 풀이 1057번 - 토너먼트 (0) | 2023.03.08 |
---|