문제: icpc.me/1514
비밀번호 A를 B로 바꾸기 위한 최소 돌림의 횟수를 구하는 문제이다.
동적 계획법을 통해 문제를 해결 할 수 있다.
dp[pos][x][y][z][flag]
=> pos번 째 자물쇠를 볼 때 x: pos번 자물쇠를 돌린 범위 y: pos+1번 자물쇠를 돌린 범위 z:pos+2번 자물쇠를 돌린 범위
(flag는 자물쇠를 돌리는 방향성)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int n, a[110], b[110], dp[110][10][10][10][2]; int modulo(int x) { while (x < 0)x += 10; return x % 10; } int func(int pos, int x, int y, int z, int w) { if (pos == n)return 0; int &ret = dp[pos][x][y][z][w]; if (ret != -1)return ret; if (modulo(x + a[pos]) == modulo(b[pos]))return ret = min(func(pos + 1, y, z, 0, 0), func(pos + 1, y, z, 0, 1)); ret = 1e9; for (int i = 1; i <= 3; i++) { if (w) { ret = min(ret, 1 + func(pos, modulo(x + i), y, z, w)); ret = min(ret, 1 + func(pos, modulo(x + i), modulo(y + i), z, w)); ret = min(ret, 1 + func(pos, modulo(x + i), modulo(y + i), modulo(z + i), w)); } else { ret = min(ret, 1 + func(pos, modulo(x - i), y, z, w)); ret = min(ret, 1 + func(pos, modulo(x - i), modulo(y - i), z, w)); ret = min(ret, 1 + func(pos, modulo(x - i), modulo(y - i), modulo(z - i), w)); } } return ret; } int main() { memset(dp, -1, sizeof(dp)); scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%1d", &a[i]); for (int i = 0; i < n; i++) scanf("%1d", &b[i]); printf("%d\n", min(func(0, 0, 0, 0, 0), func(0, 0, 0, 0, 1))); return 0; } | cs |
'알고리즘 관련 > BOJ' 카테고리의 다른 글
BOJ)9250 문자열 집합 판별 (0) | 2017.08.02 |
---|---|
BOJ)1063 킹 (0) | 2017.08.02 |
BOJ)5721 사탕 줍기 대회 (0) | 2017.08.01 |
BOJ)11560 다항식 게임 (0) | 2017.08.01 |
BOJ)10276 Jewelry Exhibition (0) | 2017.08.01 |