Closed baexxbin closed 2 weeks ago
=> 전체 집 방문(100,000) 방문시 배달&수거 과정(최대 cap만큼 50) => O(50 100,000)으로 해결 가능
// 배달하기
int capD = cap;
int d = i;
while(d >= 0) {
// 실을 수 있는 개수가 초과한다면 초과하지 않을만큼만 실기
if(capD < deliveries[d]) {
deliveries[d] -= capD;
break;
}
// 모두 실을 수 있다면 실기
capD -= deliveries[d];
deliveries[d] = 0;
d--;
}
처음에는 객체를 만들어서 풀었는데 배달상자와 수거상자가 따로 처리되다보니깐 그럴 필요가 없는것 같습니다. 그런데 왜 객체로 하면 17번에서 시간초과가 날까요,,,,, ㅎㅎㅎㅎ
long형
사용10^6
누적합
사용 (i시점으로부터 배달/수거해야할 총 양) int k = 0; // 왕복 횟수
long ans = 0;
for (int i = n - 1; i >= 0; i--) {
while (deliveries[i] > cap * k || pickups[i] > cap * k) { // 현재 위치에서 배달과 수거가 모두 완료되기위한 왕복횟수를 구해야함
ans += (i+1)* 2L; // 총거리 갱신: 현재위치에서 왕복 일어남. 해당 내용 더해줌
k++; // 왕복횟수 업데이트
}
}
return ans;
알고리즘: 그리디
시간복잡도: 1 ≤ cap ≤ 50
, 1 ≤ n ≤ 100,000
각 집을 한번만 순회하므로 O(N)
선 배달 or 수거
/ 후 cap 만큼 충전
잘못생각한 이유: 마지막 집부터 순회를 도는것 까진 아이디어를 생각했는데, 배달 or 수거가 필요한 마지막 집이 어딘지 찾는데 중점을 뒀기 때문에 많은 경우에 대해 하나씩 구현하다가 포기하고 해설 참고......😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭
질문! 그리디 같은 경우는 아이디어를 떠올려서 문제를 구현해야 하는게 많은것 같은데, 이건 문제를 많이 풀어보는게 가장 좋은 방법인가요?
그리디
for (int i = n - 1; i >= 0; i--) {
int cnt = 0;
while (deliveries[i] > delivery || pickups[i] > pickup) {
cnt++;
delivery += cap;
pickup += cap;
}
delivery -= deliveries[i];
pickup -= pickups[i];
answer += (i + 1) * 2 * cnt;
}
O(N)
(완전탐색!!!) 모든 배달과 수거
를 마치고 물류창고까지 돌아올 수 있는 최소 이동 거리
모든 배달과 수거 -> 각 집 방문 -> 전체거리 최소화 -> 멀리있는 집부터 방문해서 돌아오기
for(int i=n-1; i>=0; i--){ // 가장 먼 집부터 확인
deliver += deliveries[i];
pickup += pickups[i];
while(deliver>0 || pickup>0){ // 배달 or 수거할 택배가 있다면
deliver -= cap; // 방문한 곳은 배달 or 수거
pickup -= cap;
answer +=(i+1) * 2; // 물류창고로 다시 돌아오니까 *2
}
}
return answer;
완전 탐색은 항상 O(N^2)이 아니다....
1 <= 배달할 집의 개수 <= 100_000
1 <= 재활용 택배 상자의 최대 개수 <= 50
for(int i = n - 1; i >= 0; i--) {
d -= deliveries[i];
p -= pickups[i];
while(d < 0 || p < 0) {
d += cap;
p += cap;
// 왕복 왔다갔다 하는 거리
answer += (i + 1) * 2;
}
}
제겐 그리디, DP가 유독 왤케 어려울까요!! 연습 많이 해야겠습니다!!