https://www.acmicpc.net/problem/14867
14867번: 물통
표준 입력으로 물통 A의 용량을 나타내는 정수 a(1 ≤ a < 100,000), 물통 B의 용량을 나타내는 정수 b(a < b ≤ 100,000), 최종 상태에서 물통 A에 남겨야 하는 물의 용량을 나타내는 정수 c(0 ≤ c ≤ a), 최
www.acmicpc.net
14867 물통
알고리즘 : 메모이제이션을 활용한 BFS
얼핏보면 간단 dp같지만, 두 물통의 총량이 100,000으로 두 값을 dp배열의 크기로 사용하면 메모리초과가 납니다.
하지만 나오는 물의 경우의 수는 한정적이므로 이를 map으로 dp를 한다면 시간이 오래 걸리지만 (visited 체크시 log N)
시간내에 결과값을 얻어낼 수 있습니다. map을 활용하지 않고 배열을 사용하여 수식을 이용하고, 상대적인 수로 치환한다면 더욱 빠른 시간내에 풀이가 가능하리라 보는데 오류를 못 찾아내어 20%에서 틀려 map으로 변경했습니다 ^^;
< CODE >
#include <iostream>
#include <queue>
#include <climits>
#include <algorithm>
#include <map>
using namespace std;
struct forQ
{
int x;
int y;
int cnt = 0;
};
queue<forQ> q;
int result = -1;
map<pair<int,int>, bool> dp;
bool isChecked(int a, int b)
{
return dp[{a,b}];
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int A, B, a, b;
cin >> A >> B >> a >> b;
q.push({0,0,0});
while(!q.empty())
{
forQ cur = q.front(); q.pop();
if(dp[{cur.x,cur.y}])
continue;
dp[{cur.x,cur.y}] = true;
if(cur.x == a && cur.y == b)
{
result = cur.cnt;
break;
}
if(!isChecked(0,cur.y))
q.push({0,cur.y,cur.cnt + 1});
if(!isChecked(cur.x,0))
q.push({cur.x,0,cur.cnt + 1});
if(!isChecked(A,cur.y))
q.push({A,cur.y,cur.cnt + 1});
if(!isChecked(cur.x,B))
q.push({cur.x,B,cur.cnt + 1});
if(cur.x < A && cur.y != 0)
{
int amount = min(A - cur.x, cur.y);
if(!isChecked(cur.x+amount,cur.y-amount))
q.push({cur.x + amount, cur.y - amount, cur.cnt + 1});
}
if(cur.y < B && cur.x != 0)
{
int amount = min(B - cur.y, cur.x);
if(!isChecked(cur.x-amount,cur.y+amount))
q.push({cur.x - amount, cur.y + amount, cur.cnt + 1});
}
}
cout << result << '\n';
return 0;
}
시간 : 488ms
태그 : #BOJ 물통 #정올 물통 #KOI 물통 #백준 물통 #14867 물통 풀이
'알고리즘' 카테고리의 다른 글
[BOJ / 구현] 19535 ㄷㄷㄷㅈ (0) | 2021.06.28 |
---|---|
[BOJ / 구현] 19539 사과나무 (0) | 2021.06.28 |
[BOJ / 다차원 비트마스크 DP] 1562 계단 수 (0) | 2021.06.25 |
[BOJ / 그리디] 1202 보석 도둑 (0) | 2021.06.25 |
[BOJ / 비트마스크 DP] 1102 발전소 (0) | 2021.01.05 |