Algorithm/λ¬Έμ œν’€μ΄

[λ°±μ€€] 14501번 - 퇴사, 15486번 - 퇴사 2 (C++)

moaoh 2023. 7. 10. 23:28

문제

μƒλ‹΄μ›μœΌλ‘œ μΌν•˜κ³  μžˆλŠ” λ°±μ€€μ΄λŠ” 퇴사λ₯Ό ν•˜λ €κ³  ν•œλ‹€.

μ˜€λŠ˜λΆ€ν„° N+1일째 λ˜λŠ” λ‚  퇴사λ₯Ό ν•˜κΈ° μœ„ν•΄μ„œ, 남은 N일 λ™μ•ˆ μ΅œλŒ€ν•œ λ§Žμ€ 상담을 ν•˜λ €κ³  ν•œλ‹€.

λ°±μ€€μ΄λŠ” λΉ„μ„œμ—κ²Œ μ΅œλŒ€ν•œ λ§Žμ€ 상담을 작으라고 뢀탁을 ν–ˆκ³ , λΉ„μ„œλŠ” ν•˜λ£¨μ— ν•˜λ‚˜μ”© μ„œλ‘œ λ‹€λ₯Έ μ‚¬λžŒμ˜ 상담을 μž‘μ•„λ†“μ•˜λ‹€.

각각의 상담은 상담을 μ™„λ£Œν•˜λŠ”λ° κ±Έλ¦¬λŠ” κΈ°κ°„ Ti와 상담을 ν–ˆμ„ λ•Œ 받을 수 μžˆλŠ” κΈˆμ•‘ Pi둜 이루어져 μžˆλ‹€.

N = 7인 κ²½μš°μ— λ‹€μŒκ³Ό 같은 상담 μΌμ •ν‘œλ₯Ό 보자.

  1일 2일 3일 4일 5일 6일 7일
Ti 3 5 1 1 2 4 2
Pi 10 20 10 20 15 40 200

1일에 μž‘ν˜€μžˆλŠ” 상담은 총 3일이 걸리며, μƒλ‹΄ν–ˆμ„ λ•Œ 받을 수 μžˆλŠ” κΈˆμ•‘μ€ 10이닀. 5일에 μž‘ν˜€μžˆλŠ” 상담은 총 2일이 걸리며, 받을 수 μžˆλŠ” κΈˆμ•‘μ€ 15이닀.

상담을 ν•˜λŠ”λ° ν•„μš”ν•œ 기간은 1일보닀 클 수 있기 λ•Œλ¬Έμ—, λͺ¨λ“  상담을 ν•  μˆ˜λŠ” μ—†λ‹€. 예λ₯Ό λ“€μ–΄μ„œ 1일에 상담을 ν•˜κ²Œ 되면, 2일, 3일에 μžˆλŠ” 상담은 ν•  수 μ—†κ²Œ λœλ‹€. 2일에 μžˆλŠ” 상담을 ν•˜κ²Œ 되면, 3, 4, 5, 6일에 μž‘ν˜€μžˆλŠ” 상담은 ν•  수 μ—†λ‹€.

λ˜ν•œ, N+1μΌμ§Έμ—λŠ” νšŒμ‚¬μ— μ—†κΈ° λ•Œλ¬Έμ—, 6, 7일에 μžˆλŠ” 상담을 ν•  수 μ—†λ‹€.

퇴사 전에 ν•  수 μžˆλŠ” μƒλ‹΄μ˜ μ΅œλŒ€ 이읡은 1일, 4일, 5일에 μžˆλŠ” 상담을 ν•˜λŠ” 것이며, μ΄λ•Œμ˜ 이읡은 10+20+15=45이닀.

상담을 적절히 ν–ˆμ„ λ•Œ, 백쀀이가 얻을 수 μžˆλŠ” μ΅œλŒ€ μˆ˜μ΅μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.


μž…λ ₯

퇴사

첫째 쀄에 N (1 ≤ N ≤ 15)이 μ£Όμ–΄μ§„λ‹€.

λ‘˜μ§Έ 쀄뢀터 N개의 쀄에 Ti와 Piκ°€ 곡백으둜 κ΅¬λΆ„λ˜μ–΄μ„œ μ£Όμ–΄μ§€λ©°, 1일뢀터 NμΌκΉŒμ§€ μˆœμ„œλŒ€λ‘œ μ£Όμ–΄μ§„λ‹€. (1 ≤ Ti ≤ 5, 1 ≤ Pi ≤ 1,000)

 

퇴사2

첫째 쀄에 N (1 ≤ N ≤ 1,500,000)이 μ£Όμ–΄μ§„λ‹€.

λ‘˜μ§Έ 쀄뢀터 N개의 쀄에 Ti와 Piκ°€ 곡백으둜 κ΅¬λΆ„λ˜μ–΄μ„œ μ£Όμ–΄μ§€λ©°, 1일뢀터 NμΌκΉŒμ§€ μˆœμ„œλŒ€λ‘œ μ£Όμ–΄μ§„λ‹€. (1 ≤ Ti ≤ 50, 1 ≤ Pi ≤ 1,000)


좜λ ₯

첫째 쀄에 백쀀이가 얻을 수 μžˆλŠ” μ΅œλŒ€ 이읡을 좜λ ₯ν•œλ‹€.


예제 μž…λ ₯ 1 λ³΅μ‚¬

7
3 10
5 20
1 10
1 20
2 15
4 40
2 200

예제 좜λ ₯ 1 λ³΅μ‚¬

45

예제 μž…λ ₯ 2 λ³΅μ‚¬

10
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10

예제 좜λ ₯ 2 λ³΅μ‚¬

55

예제 μž…λ ₯ 3 λ³΅μ‚¬

10
5 10
5 9
5 8
5 7
5 6
5 10
5 9
5 8
5 7
5 6

예제 좜λ ₯ 3 λ³΅μ‚¬

20

예제 μž…λ ₯ 4 λ³΅μ‚¬

10
5 50
4 40
3 30
2 20
1 10
1 10
2 20
3 30
4 40
5 50

예제 좜λ ₯ 4 λ³΅μ‚¬

90

풀이과정

ν•΄λ‹Ή λ¬Έμ œλŠ” dpμ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ λΆ„λ₯˜λ˜μ–΄μžˆλŠ” 문제둜 μƒˆλ‘œμš΄ μ•Œκ³ λ¦¬μ¦˜ κ°œλ…μ„ λŒ€μž…μ„ ν•΄μ„œ ν’€μ–΄μ•Ό ν–ˆλ˜ λ¬Έμ œμ˜€λ‹€.

λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ΄λž€ "νŠΉμ • λ²”μœ„κΉŒμ§€μ˜ 값을 κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ 그것과 λ‹€λ₯Έ λ²”μœ„κΉŒμ§€μ˜ 값을 μ΄μš©ν•˜μ—¬ 효율적으둜 값을 κ΅¬ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜"

이라고 λͺ…μ‹œκ°€ λ˜μ–΄μžˆλŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

즉 μœ„μ™€ 같은 ν‡΄μ‚¬λ¬Έμ œμ˜ 값을 ꡬ할 λ•Œ λͺ¨λ“  경우의 수λ₯Ό λ‹€ λŒλ €λ³΄λŠ” 것이 μ•„λ‹ˆλΌ 이전에 κ΅¬ν•΄λ‘μ—ˆλ˜ λ‹€λ₯Έ 값을 μ°Έμ‘°ν•΄μ„œ ν˜„μž¬μ˜ 값을 κ΅¬ν•˜λŠ” μ‹œκ°„λ‹¨μΆ•μ„ ν•  수 μžˆλŠ” μ•Œκ³ λ¦¬μ¦˜ 방법이라고 μƒκ°ν•˜λ©΄ λœλ‹€.

 

  1일 2일 3일 4일 5일 6일 7일
κΈ°κ°„ (Ti) 3 5 1 1 2 4 2
κΈˆμ•‘ (Pi) 10 20 10 20 15 40 200
dp 0 0 0 X 0 0 0

μœ„μ— λ¬Έμ œμ— dpλ₯Ό λŒ€μž…ν•˜μ—¬ μ„€λͺ…을 ν•΄λ³΄μžλ©΄ λ¬Έμ œμ—μ„œλŠ” μ΅œμ’…μ μœΌλ‘œ 얻을 수 μžˆλŠ” μ΅œλŒ€μˆ˜μ΅μ΄ λͺ‡μΈκ°€λ₯Ό μ€‘μš”ν•œ 포인트둜 μƒκ°ν•˜λ©΄ λœλ‹€.

μ΅œλŒ€μˆ˜μ΅μ€ 결과적으둜 κ°€μž₯ λ§ˆμ§€λ§‰ 뢀뢄쀑에 해당이 λ˜κ² μ§€λ§Œ dpλΌλŠ” 것 μžμ²΄κ°€ μ΅œλŒ€μˆ˜μ΅μ΄λΌλŠ” 값을 κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ λ‹€λ₯Έ λ²”μœ„μ˜ κ°’κΉŒμ§€ μ΄μš©ν•˜μ—¬ ν™œμš©ν•˜λŠ” 방식을 μ΄μ•ΌκΈ°ν•˜κΈ° λ•Œλ¬Έμ— μ΅œλŒ€μˆ˜μ΅μ΄ λ˜κΈ°κΉŒμ§€μ˜ μ „ 과정듀이 μ–΄λ–»κ²Œ 이루어져 μžˆλŠ”κ°€λ₯Ό μ€‘μ μ μœΌλ‘œ λ΄μ„œ 값을 κ΅¬ν•˜λŠ” 방식을 μ΄μ•ΌκΈ°ν•œλ‹€.

μœ„μ— ν‘œμ—μ„œ μ΅œλŒ€μˆ˜μ΅μ΄ λ˜λŠ” 기쀀이 10+20+15=45에 해당이 λ˜λŠ” κ°’μ΄κΈ°λ•Œλ¬Έμ— 이전에 λ²Œμ–΄λ“€μ€ μˆ˜μ΅μ€ 계속 더해가며 계산이 λ˜λŠ” ν˜•μ‹μ΄λΌλŠ” 것을 λ³Ό 수 있고, μœ„μ— μžˆλŠ” ν‘œλ₯Ό κΈ°μ€€μœΌλ‘œ μ΅œμ’…μ μΈ μ΅œλŒ€μˆ˜μ΅λ§Œ μƒκ°ν•˜λŠ” 것이 μ•„λ‹ˆλΌ XλΌλŠ” 날이 있으면 그날에 얻을 수 μžˆλŠ” μ΅œλŒ€ μˆ˜μ΅μ€ λͺ‡μΈκ°€λΌκ³  λ°”κΏ” 생각을 ν•˜μ—¬ 이전에 μžˆλŠ” 값듀을 μΈμš©ν•΄μ„œ 후에 값을 κ³„μ‚°ν•˜λŠ” λ°©μ‹μœΌλ‘œ μƒκ°ν•˜λ©΄ λœλ‹€.

(dpμ—λŠ” κ·Έλ‚  λ²Œμ–΄λ“œλ¦΄ 수 μžˆλŠ” μ΅œλŒ€ 수읡이 μ νžŒλ‹€.)

  1일 2일 3일 4일 5일 6일 7일
κΈ°κ°„ (Ti) 3 5 1 1 2 4 2
κΈˆμ•‘ (Pi) 10 20 10 20 15 40 200
dp 0 0 0 10 0 0 0

 

1일차의 κ²½μš°μ—λŠ” 기간이 3일이기 λ•Œλ¬Έμ— 10에 ν•΄λ‹Ήν•˜λŠ” λ³΄μˆ˜λŠ” 4일 차에 λ“€μ–΄μ˜€λŠ” ν˜•μ‹μ΄λΌκ³  생각을 ν•  수 μžˆλ‹€. μ΄λŸ¬ν•œ ν˜•μ‹μœΌλ‘œ λͺ¨λ“  값듀을 dp에 λ‹€ λ‹΄λ‹€ 보면 

  1일 2일 3일 4일 5일 6일 7일
κΈ°κ°„ (Ti) 3 5 1 1 2 4 2
κΈˆμ•‘ (Pi) 10 20 10 20 15 40 200
dp 0 0 0 10 0 0 20

3일 μ°¨μ—λŠ” 기간이 1μ΄λΌμ„œ 4일에 λ°”λ‘œ 수읡이 λ“€μ–΄μ˜€λŠ” ν˜•μ‹μΈλ° 4일 차에 이미 ν•΄λ‹Ήν•˜λŠ” μœ„μΉ˜μ— 값이 μ ν˜€μžˆμ–΄μ„œ 값을 적을 수 μ—†λŠ” 상황이 λ‚˜μ˜€κ²Œ λœλ‹€.

그런 κ²½μš°μ—λŠ” 1일차와 3일 μ°¨κ°€ μ„œλ‘œ λ‹€λ₯Έ 경둜둜 4일 차에 도달을 ν•œ κ²½μš°λΌμ„œ 4일 차의 μž…μž₯μ—μ„œ 보면 λ‘˜ 쀑 μ–΄λ– ν•œ 값이 μ ν˜€λ„ 이전 결과에 λ”°λΌμ„œ 이미 λ„λ‹¬λ˜μ–΄ 온 값듀이기 λ•Œλ¬Έμ— 4일 μ°¨κ°€ λ‚˜μ•„κ°€λŠ” 데에 μžˆμ–΄μ„œλŠ” μ „ν˜€ 상관이 μ—†λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

κ·Έλž˜μ„œ ν•΄λ‹Ή λ¬Έμ œμ—μ„œλŠ” μ΅œλŒ€ μˆ˜μ΅μ„ κ΅¬ν•˜λŠ” ν˜•μ‹μœΌλ‘œ λ¬Έμ œκ°€ μ£Όμ–΄μ‘ŒκΈ° λ•Œλ¬Έμ— 4일차에 이미 μ ν˜€μžˆλŠ” dp에 κ°’κ³Ό μƒˆλ‘­κ²Œ λ“€μ–΄μ˜¬ 값을 λΉ„κ΅ν•΄μ„œ 더 큰 값을 적으면 λ˜λŠ” 방식이닀. DP [4일 μ°¨] = max(DP [4일 μ°¨], N(μƒˆλ‘­κ²Œ λ“€μ–΄μ˜¬ κ°’))

μœ„μ— κ²½μš°μ—λŠ” 1일차의 값도 10이고 3일 차의 값도 10μ΄λ―€λ‘œ 크게 μƒκ΄€ν•˜μ§€ μ•Šκ³  μ§„ν–‰ν•˜κ²Œ λœλ‹€.

  1일 2일 3일 4일 5일 6일 7일
κΈ°κ°„ (Ti) 3 5 1 1 2 4 2
κΈˆμ•‘ (Pi) 10 20 10 20 15 40 200
dp 0 0 0 10 30 0 20

μœ„μ™€ 같이 4일 차의 ν•΄λ‹Ήν•˜λŠ” 값을 5일 μ°¨(기간이 1μ΄λ―€λ‘œ)에 적어야 ν•˜λŠ” κ²½μš°μ—λŠ” κ³„μ‚°ν•˜λŠ” 날에 dp에 이미 μ ν˜€μžˆλŠ” 값을 κ·ΈλŒ€λ‘œ κ°€μ§€κ³ 

5일 차에 적으면 λœλ‹€. (4일 μ°¨ : 20 + dp : 10 = 30 )

  1일 2일 3일 4일 5일 6일 7일
κΈ°κ°„ (Ti) 3 5 1 1 2 4 2
κΈˆμ•‘ (Pi) 10 20 10 20 15 40 200
dp 0 0 0 10 30 0 45

μ΄λŸ¬ν•œ ν˜•μ‹μœΌλ‘œ 계속 계산을 ν•˜λ‹€ 보면 μš°λ¦¬κ°€ κ΅¬ν•˜μžκ³  ν–ˆλ˜ μ΅œλŒ€μˆ˜μ΅μ˜ 값을 찾을 수 μžˆλŠ” 것을 μ•Œ 수 μžˆλ‹€.

μ΄λŸ¬ν•œ ν˜•μ‹μœΌλ‘œ μ „κ°œκ°€ λœλ‹€κ³  생각을 ν•˜λ©΄ λœλ‹€.

 

좔가적인 λ°˜λ‘€λ‘œλŠ” μœ„μ— ν‘œμƒμœΌλ‘œλŠ” 6일 차에 dp(μ΅œλŒ€μˆ˜μ΅)이 0으둜 μ ν˜€μžˆμ§€λ§Œ 5일차에 수읡이 30μ΄λ―€λ‘œ

6일차에 일을 μ•„μ˜ˆ μ•ˆ ν•œλ‹€κ³  해도 6일 차의 μˆ˜μ΅μ€ 이전에 μ΅œλŒ€ μˆ˜μ΅κ°’μ„ κ°€μ Έμ•Ό ν•œλ‹€.

κ·Έλž˜μ„œ 진행을 ν•΄κ°€λ©΄μ„œ dp의 값이 λΉ„μ›Œμ Έ μžˆλ‹€λ©΄ μ±„μ›Œ λ„£μ–΄μ£ΌλŠ” 식도 μΆ”κ°€μ μœΌλ‘œ λ„£μ–΄μ€˜μ•Ό ν•œλ‹€.


14501번 - 퇴사
15486번 - 퇴사 2

14501λ¬Έμ œκ°€ 15486λ¬Έμ œμ™€ ν˜•μ‹λ§Œ λ˜‘κ°™κ³  μ£Όμ–΄μ§€λŠ” 크기만 λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— ν‡΄μ‚¬λ¬Έμ œμ˜ μ½”λ“œλ₯Ό dpν˜•μ‹μœΌλ‘œ ꡬ성을 ν•΄λ‘μ—ˆλ‹€λ©΄ 퇴사2 λ¬Έμ œλ„ λ°°μ—΄κ°’λ§Œ λ°”κΏ”μ„œ κ·ΈλŒ€λ‘œ ν’€ 수 μžˆμ—ˆλ‹€.

 

code

// 14501번 - 퇴사
#include <iostream>
#include <algorithm>

int		main(void)
{
	int n, max = -1;
	int tp[16][2] = {0,}, dp[16] = {0,};

	std::cin >> n;
	for (int i = 0; i < n; i++)
		std::cin >> tp[i][0] >> tp[i][1];

	for (int i = 0; i <= n; i++) {
		int deadline = i + tp[i][0];
		if (max > dp[i]) dp[i] = max;
		if (deadline <= n)
			dp[deadline] = std::max(dp[deadline], tp[i][1] + dp[i]);
		if (dp[i] > max) max = dp[i];
	}
	std::cout << max;

	return (0);
}
// 15486번 - 퇴사 2
#include <iostream>
#include <algorithm>

int		main(void)
{
	int n, max = -1;
	int tp[1600000][2] = {0,}, dp[1600000] = {0,};

	std::cin >> n;
	for (int i = 0; i < n; i++)
		std::cin >> tp[i][0] >> tp[i][1];

	for (int i = 0; i <= n; i++) {
		int deadline = i + tp[i][0];
		if (max > dp[i]) dp[i] = max;
		if (deadline <= n)
			dp[deadline] = std::max(dp[deadline], tp[i][1] + dp[i]);
		if (dp[i] > max) max = dp[i];
	}
	std::cout << max;

	return (0);
}

 


ν›„κΈ°

dpλΌλŠ” κ°œλ…μ„ μ΄λ²ˆμ— μƒˆλ‘­κ²Œ λ‹€μž‘μžλΌλŠ” λŠλ‚ŒμœΌλ‘œ μ•Œκ³ λ¦¬μ¦˜μ— λŒ€ν•΄μ„œ 곡뢀λ₯Ό ν•΄λ΄€μ—ˆλŠ”λ° ν™•μ‹€νžˆ μ–΄λ ΅λ‹€λŠ” λŠλ‚Œμ„ 많이 λ°›μ•˜λ‹€.

μ½”ν…Œλ₯Ό λ³΄κ±°λ‚˜ 기본적으둜 κ°€μž₯ 많이 μ“°μ΄λŠ” μ•Œκ³ λ¦¬μ¦˜ 쀑에 ν•˜λ‚˜μ΄κΈ° λ•Œλ¬Έμ— μ΅μˆ™ν•΄μ§ˆ λ•ŒκΉŒμ§€ dpλ₯Ό 계속 풀어봐야 ν•  κ±° κ°™λ‹€.