작성
·
369
·
수정됨
1
최근에 다시 자바스크립트로 돌리면서, 기존에 파이썬으로 했던 것들 다시 모두 자바스크립트로 풀어보면서 문제 풀어보니, 발견했습니다.
이거 첫번째 가정을, 그리디로 접근하면 해결 안되는 문제인것같습니다. 이후 가정들은 당연히 그리디 관념으로 최적값 찾을 수 있는데, 첫번째 가정부터 그리디로 접근하면 해결되는 문제가 아니라서 어긋나기때문에, 그리디관념이 통하지 않는 문제인것같습니다.
완전탐색해버리거나, 시간 더 줄이려면 백트래킹 가지치기 해야하는 문제인것같습니다.
입력입니다!
7
172 67
183 65
179 61
178 62
177 63
170 72
181 60
기존 풀이(무조건 183선발) 가 내주는 답 : 3
감독 현수가 원할 것 같은 답 : 6
그리디로 가장 키 큰 사람 무조건 선발하는 과정이 풀이에서 오류인것같습니다.
183 선발 가정하고 cnt 값 구하고,
그다음 181 선발 가정하고 cnt값 구하고,
쭉 다음 순으로 선발 가정하고 cnt값 구하는데,
만약 어떤 사람 선발 가정하고 cnt값 구하는데
남은 사람 수 다 합해도 기존 Max cnt보다 적을 경우,
백트레킹 가지치기로 break 혹은 return 끊어버리는게 맞는것같습니다.
풀이1. 이중포문
const input = require("fs")
.readFileSync("input.txt")
.toString()
.trim()
.split("\n");
const n = parseInt(input[0]);
const arr = Array.from(Array(5), () => []);
for (let i = 0; i < n; i++) {
arr[i] = Array.from(input[i + 1].trim().split(" ")).map((v) => parseInt(v));
}
function solution(n, arr) {
arr.sort((a, b) => b[0] - a[0]);
let cnt = 0;
let largest = 0;
let res = 0;
for (let i = 0; i < n; i++) {
largest = arr[i][1];
cnt += 1;
if (res >= n - i) {
break;
}
for (let j = i + 1; j < n; j++) {
if (arr[j][1] > largest) {
largest = arr[j][1];
cnt += 1;
}
}
res = Math.max(res, cnt);
cnt = 0;
}
console.log(res);
}
solution(n, arr);
풀이2. DFS
const input = require("fs")
.readFileSync("input.txt")
.toString()
.trim()
.split("\n");
const n = parseInt(input[0]);
const arr = Array.from(Array(5), () => []);
for (let i = 0; i < n; i++) {
arr[i] = Array.from(input[i + 1].trim().split(" ")).map((v) => parseInt(v));
}
let cnt = 0;
let res = 0;
//const list = [];
function DFS(s, weight) {
if (s < 0) return;
if (cnt + n - s <= res) {
cnt -= 1;
s -= 1;
return;
}
for (let i = s; i < n; i++) {
if (arr[i][1] > weight) {
cnt += 1;
//list.push(arr[i][1]);
DFS(i + 1, arr[i][1]);
//list.pop();
}
}
res = Math.max(res, cnt);
//console.log(list);
cnt -= 1;
}
function solution(n, arr) {
arr.sort((a, b) => b[0] - a[0]);
DFS(0, 0);
console.log(res);
}
solution(n, arr);
답변 2
0
질문자님이 이전 문제들 영향으로 조금 잘못 이해하셔서 그렇습니다. 문제도 살짝 헷갈리게 써있긴 합니다만..
출력 설명에 최대 라는 글자를 빼고 나서 문제를 처음부터 다시 읽어보시면 문제 의도가 이해가 가실겁니다.
0
안녕하세요^^
씨름선수 문제는 "어느 한 사람에게라도 내가 키와 몸무게 모두 작으면 선발이 되지 않는다는 의미입니다"
위에 예제는 3이 답입니다.
키순으로 정렬했다면
183 65는 어느 누구에게도 키와 몸무게 모두 작지는 않습니다. 그래서 선발되는 것입니다.
181 60은 183 65와 비교해서 키, 몸무게 모두 작기 때문에 선발되지 않습니다.
179 61은 183 65와 비교해서 키, 몸무게 모두 작기 때문에 선발되지 않습니다.
...
172 67은 키는 위에 모든 사람보다 작지만 몸무게는 위에 사람 누구에게도 작지 않습니다. 그래서 선발됩니다.
170 72도 키는 위에 모든 사람보다 작지만 몸무게는 위에 사람 누구에게도 작지 않습니다. 그래서 선발됩니다.
안녕하세요^^
무조건 최대인원을 뽑으라는 문제가 아니고 문제가 준 조건을 지키면서 선발을 했을 때의 최대인원을 구하라는 것입니다. 이 문제는 그리디로 유명한 문제입니다.
백준에 "신입사원" 문제가 이 문제와 동일 문제이니 살펴보세요.
안녕하세요! 자꾸 질문해서 죄송합니다..
그렇다면, 만약 제가 문제의 코치라고 가정했을시,
지원을
183 150
180 60
179 61
178 62
177 63
176 64
175 65
174 64
이렇게 8명이 지원했다 가정할 때,
씨름단 선수구성에 관해서 문제에서 요구하는게,
1.처음부터 지원서 전체 대상자를 기준으로 하는 것인가요? (기존 문제 조건)
그렇게 되면,
183 한명때문에, 나머지 7명을 탈락시키게 되는데, 제가 이렇게 1명 뽑아야하는게 문제 의도인가요?
아니면
2.제가 뽑은 사람들 기준으로 할 때와 같이,
183 탈락시키고 나머지 7명 선발해서 7명으로 운영하는 문제인가요?
문제에서 요구 및 목표는 분명 조건에 부합하는 지원자들 중 최대로 선발하겠다. 이게 의도이자 목표인것같은데
전제 조건 1번, 2번 둘 중 당연히 2번으로 전제 조건 가정해야 문제 의도(감독으로서 좋은 성적 내기위해 많은 선발) 와 의미적으로 매칭되는것 아닌가요?
문제 의도와 목표가 햇갈립니다! . 그리디를 위한 문제인지(1번 가정), 문제해결을 위한 문제인지(2번 가정)
결론적으로
이 문제가 주어졌을 때, 문제해결을 위해 특정 관념이나 기법을 사용해 해결할 수 있다.
혹은
이 문제는 이렇게 풀도록 설계되서 문제 출제되었다.
제가 지난 문제들 다시 풀어보면서,
특정 이 문제에서 유난히 햇갈렸던 이유가 저 2개의 생각이 문제 의도를 파악하고 답을 구하는데 있어서 충돌해서 그런것같습니다!
<문제>
현수는 씨름 감독입니다. 현수는 씨름 선수를 선발공고를 냈고, N명의 지원자가 지원을 했습
니다. 현수는 각 지원자의 키와 몸무게 정보를 알고 있습니다.
현수는 씨름 선수 선발 원칙을 다음과 같이 정했습니다.
“다른 모든 지원자와 일대일 비교하여 키와 몸무게 중 적어도 하나는 크거나, 무거운 지원자
만 뽑기로 했습니다.” (1번 가정, 기존 문제)
“선발한 인원과 일대일 비교하여 키와 몸무게 중 적어도 하나는 크거나, 무거운 지원자
만 뽑기로 했습니다.” (2번 가정, New)
<>
현수는 아마 씨름대회에서 좋은 성적 내기는 글른것같습니다. 다른 우수한 인원들 선발하지 못하고,
183cm 150kg 고도비만 한명 지원한 순간 끝나니 말이죠.
현수가 좋은 성적내기 위해선 공고부터 수정해야할것 같습니다 ㅎㅎ..