발상
특정 자물쇠 인덱스에서 선택할 수 있는 동작은 2가지다.
- 양의 방향으로 돌리기
- 음의 방향으로 돌리기 양의 방향으로 돌릴 경우, 돌린 양만큼 다음 모든 인덱스들에 영향을 주게 된다. 자물쇠 상태를 일일이 저장하지 않아도 앞선 인덱스에서 양의 방향으로 돌린 횟수만 알 수 있으면 현재 자물쇠 상태를 알 수 있다. 따라서 인자는 자물쇠 인덱스와 현재 인덱스 앞에서 양의 방향으로 돌린 횟수의 합이다. 또한 각 인덱스마다 10개의 숫자가 있으므로 돌린 횟수의 합은 10으로 나눈 나머지만 저장해도 된다. 순차적으로 현재 인덱스의 자물쇠 숫자를 양과 음으로 돌려 목표값에 맞추며, ‘현재 인덱스를 맞추기 위해 돌려야 하는 횟수 + 양과 음으로 돌렸을 때 이후 추가로 돌려야 하는 횟수’의 합이 작은 것을 고르면 된다.
점화식
양의 방향으로 돌렸을 때, 음의 방향으로 돌렸을 때 2가지를 모두 수행해보고 더 작은 케이스를 선택한다.
코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int n; string s, d;
vector<vector<int>> dp;
int r(int c, int sp) {
if (c == n) return 0;
if (dp[c][sp] != -1) return dp[c][sp];
int psp = (d[c] - '0' - (s[c] - '0' + sp) % 10 + 10) % 10;
int nsp = 10 - psp;
int s1 = r(c + 1, (sp + psp) % 10) + psp;
int s2 = (nsp == 10 ? 21e8 : r(c + 1, sp) + nsp);
return dp[c][sp] = s1 < s2 ? s1 : s2;
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
cin >> n; dp = vector<vector<int>>(n + 1, vector<int>(10, -1));
cin >> s >> d;
cout << r(0, 0);
return 0;
}