らての精進日記

修行をします

aoj2157:Dial Lock

解法

A[x]!=B[x]となるようなxの中で最小のものをとり、iとする。
i番目の桁より左は既に完成してるので、存在しないものとして考えても問題ない。
i番目の桁を合わせるために、少なくとも一度はi番目を含むような区間を変更しなくてはならない。
すなわち、少なくとも1度は区間[i,j](i<=j< N |この記事では、0-indexedで考えます)に操作する必要があります。
もし区間[i,j]と区間[i,k](i<=j< k < N)に操作するとき、回す量を適当に調整すれば、
区間[i,j]と区間[j+1,k]への2つの操作で全く同じ効果を得ることができる。
よって、本質的には、i番目を左端とする操作は1度だけでいい。

上のような考え方を再帰的に適用して考えると、以下のような深さ優先探索をすればいい。

dfs(n):
・n==Nなら、0を返す。
・A[n]==B[n]ならdfs(n+1)を返す。
区間[i,j]への変更を行い、dfs(n+1)+1を得る。これをi<=j< Nを満たすすべてのjについて試す。


dfs(0)を出力すればokです。

計算量は、O(K! * K)で、K<=10なのでたぶん通ります。

コード

#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

int N;
int A[11],B[11];
int dfs(int n){
    if(n==N)return 0;
    if(A[n]==B[n])return dfs(n+1);

    int t=B[n]-A[n];
    if(t<0)t+=10;
    int ret=1001001001;
    for(int i=n+1;i<=N;i++){
        for(int j=n;j<i;j++)A[j]=(A[j]+t)%10;
        chmin(ret,dfs(n+1)+1);
        for(int j=n;j<i;j++)A[j]=(A[j]-t+10)%10;
    }
    return ret;
}

signed main(){
    while(cin>>N,N){
        string S,T;
        cin>>S>>T;
        rep(i,N){
            A[i]=S[i]-'0';
            B[i]=T[i]-'0';
        }
        cout<<dfs(0)<<endl;
    }
    return 0;
}