www.acmicpc.net/problem/8980

 

8980번: 택배

입력의 첫 줄은 마을 수 N과 트럭의 용량 C가 빈칸을 사이에 두고 주어진다. N은 2이상 2,000이하 정수이고, C는 1이상 10,000이하 정수이다. 다음 줄에, 보내는 박스 정보의 개수 M이 주어진다. M은 1이

www.acmicpc.net

1. 풀이방법

 

 - 그리디 문제인데 매우 까다로웠다...

 

 - 처음에 문제의 설명 방식대로 구현을 하다 보면 반례도 잘 떠오르지 않고 매우 어려웠다...

 

 - 결국 참고한 게시판의 답변입니다

 

   (www.acmicpc.net/board/view/6327) 게시판의 plzrun 님의 답변을 보면

 - 왜 도착지를 기준으로 정렬을 해야하는 지를 잘 알 수 있다.

 

 - 처음 구현한 것도 앞마을 부터 차례대로 박스를 올리는데 뭐가 틀렸지? 를 한참 생각했지만...

 

 - 문제점은 출발마을을 앞부터 차례대로 기준으로 삼으며 도착지가 가까운 마을 부터 박스를 올린 것이다.

 

 - 핵심은 1,2,3,... 시작마을부터 차례대로 살피는게 아닌 무조건 도착지가 앞 쪽인 택배박스 부터 올려야 최대의

   양을 배달 할 수 있다.

 

 

 

 

2. 주의사항

 

 - 위의 것을 깨닫고도 구현을 생각하는 것도 꽤나 까다로웠습니다..(저는...ㅠㅠ)

 

 - 문제의 시작부터 마을을 살피는 것으로 생각해서 그 생각에서 벗어나기가;;;

 

 - 결국 해결한 것은 마을에서의 트럭의 가용용량을 배열로 선언해 저장하고, 박스들을 살펴가며

   마을 별 가용용량을 조절해주는 식으로 구현하였습니다.

 

 

 

 

3. 나의코드

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;

struct box {
	int start;
	int end;
	int weight;
};
int N,C; //마을의 수 , 트럭의 용량
int M; // 박스정보의 수
int x, y, weight;
int result;
int truck[2001]; //마을 별 트럭의 공간을 표시하기 위해서 (트럭에 올라가있는 박스의 상태)

bool compare(box &lhs, box &rhs) {
	if (lhs.end < rhs.end) return true;
	else if (lhs.end == rhs.end) {
		if (lhs.start <= rhs.start) return true;
		else return false;
	}
	else return false;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N >> C; //마을 수 와 트럭의 용량
	cin >> M;
	vector<box> sendbox(M);
	for (int i = 0; i < M; i++) {
		cin >> sendbox[i].start >> sendbox[i].end>>sendbox[i].weight;
	}
	sort(sendbox.begin(), sendbox.end(), compare);

	for (int i = 0; i < M; i++) {
		int cnt = 0;
		for (int j = sendbox[i].start; j < sendbox[i].end; j++) {
			cnt = max(truck[j], cnt);
		}
		result += min(sendbox[i].weight, C - cnt); //박스를 올리자 (담을 수 있는 양이 더 적으면 그 만큼만 올릴 수 있다)
		for (int j = sendbox[i].start; j < sendbox[i].end; j++) { //그 만큼 지나가는 마을에서의 트럭의 용량에서 빼줌
			truck[j] += min(sendbox[i].weight, C - cnt);
		}
	}
	cout << result << "\n";
	return 0;
}

'알고리즘 문제풀이 > 그리디' 카테고리의 다른 글

백준 1439 [C++]  (0) 2020.10.16
백준 1969 : DNA  (0) 2020.03.24
백준 1138  (0) 2020.02.28
백준 1049  (0) 2020.02.23
백준 1946  (0) 2020.02.23

그리디 알고리즘이란?

->  탐욕알고리즘 이라고도 불리우며, 전체적인 그림을 보지 않고 각각의 단계에서 최상의 선택들을 반복 함으로써 결과를

      도출 해내는 방법이다.

 

-> 사실 대부분의 경우 최적의 해가 아닐 가능성이 높다.

 

-> 간단한 예시로 트리의 각각의 노드의 임의의 정수가 있다. 트리의 루트노드 부터 리프 노드가 나올 때 까지 탐색 하여 그 합을 도출    

    하는 데 그 합이 가장 큰 경우의 수 를 구하려고 한다.

 

-> 이 경우 자식노드로 내려가면서 그 단계마다 가장 큰 자식 노드를 선택할 경우 나중에 전체의 합은 가장 큰 경우의 수가 아닐 가능성       이 매우 높다 ( 물론 우연히 맞을 수 도 있다.)

 

 

 

정당성 을 찾자

-> 그래서 어떠한 문제가 주어졌을 때 이 문제는 그리디 알고리즘을 이용하면 최적의 해를 구할 수 있겠다 라는 것을 생각 하기 위해서       왜 각각의 단계에서 최적의 선택을 했을 떄 전체도 최적의 경우가 되는지에 대한 정당성을 스스로 찾을 수 있어야 한다

 

-> 그 정당성을 찾음으로써 그리디 알고리즘을 사용할 경우 최적의 해가 나오는 구나 라는 생각을 할 수 있다.

 

-> 가장 대표적이면서도 기본적인 예시로 동전 거슬러주는 문제가 있는데, 문제를 아마 풀어보신 분들이 많을 것이라 생각된다.

 

-> 860 원을 거슬러 줘야 하는 경우 라고 가정하자( 500원, 100원 , 50원, 10원은 무한히 가지고 있다고 하자)

 

-> 가장 큰 단위의 동전인 500원 부터 가능한 많이 사용하고 그 다음 100원을 가능한 많이...! 이런 식으로 그리디 알고리즘을 사용하면

      가장 적은 수의 동전으로 거슬러 줄 수 있다.(500원 1 , 100원 3, 50원 1, 10원 1 ---> 총 6개의 동전 )

-> 단, 이러한 아이디어를 생각 했을 때 저 경우의 수 가 왜 최적인지 정당성을 찾아야 한다.

 

-> 이 경우에는 바로 큰 수의 동전들이 모두 작은 수의 동전들의 배수 라는 것이다 (나누어 떨어진다.)

 

-> 만약 400원 짜리 동전도 있었다고 가정을 하면 그리디 알고리즘을 사용하면

     (500원 1, 100원 3, 50원 1, 10원 1) --> 총 6개의 동전 사용 --->최적이 아니다!!!

     (400원 2, 50원 1, 10원 1) --> 총 4개의 동전 사용 

 

-> 이 경우는 500원이 400원의 배수 (나누어지지) 가 아니기 때문에 그리디 알고리즘을 사용할 경우 최적의 해가 나온다는 정당성을  

     가질 수 없다. 

'알고리즘' 카테고리의 다른 글

이진 탐색 트리 - Binary Search Tree  (0) 2020.04.24

https://www.acmicpc.net/problem/1541

 

1541번: 잃어버린 괄호

첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 많이 연속되는 숫자는 없다. 수는 0으로 시작할 수 있다.

www.acmicpc.net

-입력, 출력은 문제를 통해 쉽게 파악가능하고

 

- 이제 입력을 어떻게 받아와서 이론적으로는 -가 나오면 괄호를 열고

 

- 다음 -가 오기전에 괄호를 닫는 것인데

 

- 구현을 할 때 -가 처음나오면 check를 하고 tmp로 다음 연산부호가 오기전에 더해주고(string 즉 한글자씩이므로)

 

- 그다음부터는 그냥 -부호 붙은 수는 +붙은 수 그냥 다 빼주면 됩니다.

 

- 왜냐? 괄호는 무제한 이니까.....! 자신이 +면 가장 가까운곳에있는 -와 묶어서 빼면 되니깐....

<필기>

<코드>

 

'알고리즘 문제풀이 > 그리디' 카테고리의 다른 글

백준 1946  (0) 2020.02.23
백준 1120  (0) 2020.02.23
백준 2875  (0) 2020.02.11
백준 10610  (0) 2020.02.10
백준 2217  (0) 2020.02.10

동전 문제입니다.

 

처음에 입력조건을 꼼꼼하게 파악하지 않아 다른 경우의 수 를 생각 하다가

 

다시 문제를 보니 생각보다 훨씬 쉬운 문제였습니다..

 

필기노트에 기재되어 있습니다.

 

<필기>

 

<코드>

'알고리즘 문제풀이 > 그리디' 카테고리의 다른 글

백준 2875  (0) 2020.02.11
백준 10610  (0) 2020.02.10
백준 2217  (0) 2020.02.10
백준 1931  (0) 2020.02.05
백준 11399  (0) 2020.02.05

+ Recent posts