C++/공부 정리
dp 연습
sondiaa
2022. 5. 25. 14:07
탑다운과 바텀업 두가지가 대표적인 풀이이며, 설계를 하고 풀어야 수월함.
#include <iostream>
using namespace std;
int map[6][3] = {
0, 0, 0,
3, 5, -1,
9, -1, 1,
10, 5, 20,
-1, 5, 6,
15, 1, 5
}, cal[6][3], direct[3][2] = {1, -1, 1, 0, 1, 1};
int main()
{
for(int i=0; i<3; i++)
cal[5][i] = map[5][i];
for(int i=4; i>=0; i--)
{
for(int j=0; j<3; j++)
{
if(map[i][j] == -1) continue;
for(int k=0; k<3; k++)
{
int dy = direct[k][0] + i;
int dx = direct[k][1] + j;
if(dx > 2 || dx < 0) continue;
if(map[dy][dx] == -1) continue;
if(cal[i][j] < cal[dy][dx] + map[i][j])
cal[i][j] = cal[dy][dx] + map[i][j];
}
}
}
for(int i=0; i<3; i++)
{
cout << cal[0][i] << ' ';
}
return 0;
}
최소 동전 갯수 구하기
#include <iostream>
#include <algorithm>
using namespace std;
int coin, num[3] = {10, 50, 70};
int getCnt(int cost)
{
if(cost < 0)
return 1e9;
if(cost == 0)
return 0;
int cnt = 1e9;
for(int i=0; i<3; i++)
{
cnt = min(cnt, getCnt(cost - num[i]) + 1);
}
return cnt;
}
int main()
{
cin >> coin;
cout << getCnt(coin);
return 0;
}
메모이제이션 : 이미 구한 값을 재사용하는 것
피보나치 수열을 구하는 것이 메모이제이션을 적용할 수 있는 가장 쉬운 경우이다.
#include <iostream>
using namespace std;
long long num[100000];
long long fibo(int n)
{
if(num[n] != 0) return num[n];
if(n == 0) return 0;
if(n == 1) return 1;
return num[n] = fibo(n-1) + fibo(n-2);
}
int main()
{
num[1] = 1;
cout << fibo(20);
return 0;
}
문제에 따라 바텀업, 탑다운 방식의 차이가 있음.
문제마다 어떤 것으로 풀 지 정하는 것은 자신의 감 즉, 많이 풀수록 느낌이 온다.
탑다운의 경우 반복되는 동작이 매우 많기 때문에 메모이제이션을 사용해야 바텀업과 동일한 성능이 나온다.
메모이제이션을 사용하여 동전 최소 갯수 구하기
#include <iostream>
using namespace std;
int coin, num[100000], money[4] ={10, 50, 70, 100};
int getMinCnt(int cost)
{
if(cost < 0)
return 1e9;
if(cost == 0)
return 0;
if(num[cost] != 1e9)
return num[cost];
for(int i=0; i<4; i++)
{
num[cost] = min(num[cost], getMinCnt(cost - money[i]) + 1);
}
return num[cost];
}
int main()
{
cin >> coin;
fill(num, num+100000, 1e9);
cout << getMinCnt(coin);
return 0;
}