해결된 질문
작성
·
39
0
int go(int here, int num, int prev){
if(here == v.size()) return 0;
if(dp[here][num]) return dp[here][num];
int cost = max(0, t - v[here].second);
int real_cost = (prev >= cost) ? 0 : cost - prev;
int & ret = dp[here][num];
if(num - real_cost >= 0){
return ret = max(go(here + 1, num - real_cost, cost)+ v[here].first, go(here + 1, num, 0));
}else return ret = go(here + 1, num, 0);
}
go()함수에서 ret를 대입하는 부분에서 이해가 가질 않습니다.
if(num - real_cost >= 0)
의 경우
첫번째 인자는 친구를 투입한 경우 이므로 cost만큼의 부족한 인원의 친구가 있기때문에 cost를 넘겨주는 것으로 이해했습니다.
두번째 인자에서 0으로 넘겨주는데 이전에 투입된 친구들은 그대로 있어야 하니까 0이 아닌 prev를 넘겨줘야하는 것 아닌가요? 왜 0으로 넘겨주는 것인가요?
답변 2
0
안녕하세요 ㅎㅎ
두번째 인자에서 0으로 넘겨주는데 이전에 투입된 친구들은 그대로 있어야 하니까 0이 아닌 prev를 넘겨줘야하는 것 아닌가요? 왜 0으로 넘겨주는 것인가요?
-> 저 prev의 의미는 이전 친구비용을 뜻합니다. 현재 위치에서 친구를 사용하지 않았기 때문에 다음 단계에서는 이전 친구비용이 0이 되는 것을 의미합니다.
또한, 코드를 볼까요?
미리 만들어놓은 카운팅배열을 기반으로 친구수가 달라질때를 기준, 구간을 나눴죠?
for(int i = 2; i <= n; i++){
if(temp != cnt[i]){
v.push_back({_count, temp});
_count = 0;
temp = cnt[i];
}
_count++;
}
v.push_back({_count, temp});
이걸 기반으로 로직을 짜게 되면
예를 들어 2, 3 이렇게 친구가 필요할 경우.
2명 씀 -> prev = 2 -> 그 다음 3 - 2 = 1이 필요함.
0명 씀 -> prev = 0 -> 그 다음 3이 필요함.
이런식으로 되는 것입니다.
또 질문 있으시면 언제든지 질문 부탁드립니다.
좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)
감사합니다.
강사 큰돌 올림.
안녕하세요 ㅎㅎ
먼저 좋은 의견 주시며 날카롭게 지적하신것에 대해 감사의 말씀을 드립니다.
예리한 지적이며 해당 부분은 제가 틀린 것 같습니다.
그래서 현재 구간에서 친구를 추가하지 않더라도 0이 영선이 친구들을 이전에 넣었던 친구들 인원을 그대로 계속 넘겨줘야한다고 생각합니다.
-> 음 근데 그냥 계속 넘겨주는 것은 아니구요. 이게 예를 들어 필요한 부분이 4, 5 라고 했을 때는 -> 계속 넘겨주어야 합니다. 5일 때 4를 넘겨 주어야 합니다. 그러나 3이 필요한데 이미 3이 충족될 경우 0을 넘겨주는 등으로 prev가 조정될 필요는 있습니다.
수정된 코드는 다음과 같습니다.
#include<bits/stdc++.h>
using namespace std;
int n, m, k, t, a, b, cnt[301], dp[301][301];
vector<pair<int, int>> v;
int go(int here, int num, int prev){
if(here == v.size()) return 0;
if(dp[here][num]) return dp[here][num];
int cost = max(0, t - v[here].second);
int real_cost = (prev >= cost) ? 0 : cost - prev;
int & ret = dp[here][num];
if(cost == 0)prev = 0;
if(num - real_cost >= 0){
return ret = max(go(here + 1, num - real_cost, cost)+ v[here].first, go(here + 1, num, prev));
}else return ret = go(here + 1, num, prev);
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n >> m >> k >> t;
for(int j = 0; j < m; j++){
cin >> a >> b;
for(int i = a; i < b; i++)cnt[i] = min(t, ++cnt[i]);
}
int temp = cnt[1];
int _count = 1;
for(int i = 2; i <= n; i++){
if(temp != cnt[i]){
v.push_back({_count, temp});
_count = 0;
temp = cnt[i];
}
_count++;
}
v.push_back({_count, temp});
cout << go(0, k, 0) << "\n";
return 0;
}
해당 코드는 오늘내로 반영하도록 하겠습니다.
감사합니다.
강사 큰돌올림.
0
안녕하세요, 인프런 AI 인턴입니다.
질문해주신 내용과 관련된 부분에 대해 설명드리겠습니다.
이 문제는 dp
(동적 계획법)를 사용하여 이전 단계(즉, 여기에서는 here
구간)에서 인원이 충족되었는지를 추적하며 최대 값을 계산하는 문제로 보입니다.
if(num - real_cost >= 0)
의 의미: 여기에서 num
은 현재 필요한 인원수를 나타내며, real_cost
는 현재 구간에서 필요한 추가 인원수를 의미합니다. num - real_cost >= 0
은 현재 필요한 인원수가 충족 가능함을 확인하는 조건이 됩니다.
두 번째 인자에서 0
을 넘기는 이유: go(here + 1, num, 0)
에서 0
을 넘기는 것은 다음 구간에서는 이전 구간에서의 충족 여부를 재고하지 않고, 무조건 새로운 기준으로 시작하겠다는 의미입니다. 이를 통해 각 구간은 독립적으로 현재 구간에서 필요한 인원을 충족하기 위해 얼마나 더 필요한지를 고려하게 됩니다.
이를 통해 각 here
구간마다 독립적으로 해당 구간 내에서의 최대 값을 계산할 수 있게 하여, 전체적인 최적 솔루션을 찾게 됩니다.
앞서 설명드린 개념을 더욱 자세히 이해하고 싶다면 관련된 답변이 있는 게시물을 참고하시면 좋습니다. 유사한 질문이 포함된 게시물이 아래에 있습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
강사님 한번 들어간 친구들은 욱제 및 영선이의 친구들을 제외한 파티 인원이 T명 일때까지는 쭉 있어야하니까 0이 아닐 것 같습니다.
t = 3 일때,
파티 초대 인원 2 + 영선이 친구 2 = 4 되더라도
영선친구를 1명 빼는 것이 아닌 그대로 유지하는 것이 맞는 것 같습니다.
그래서 현재 구간에서 친구를 추가하지 않더라도 0이 영선이 친구들을 이전에 넣었던 친구들 인원을 그대로 계속 넘겨줘야한다고 생각합니다.
예를 들어
지금 알려주신 코드를 입력해도 100점이 나오긴합니다.
아마 추가 테스트케이스 요청이 반영되지 않아서 인 것 같아 그런 것 같습니다.
그러나 제가 문제를 잘 못 이한 것이라면 죄송합니다.