Problem:
Score: 500 points

Problem Statement

In the Kingdom of AtCoder, only banknotes are used as currency. There are 10^{100}+1 kinds of banknotes, with the values of 1, 10, 10^2, 10^3, \dots, 10^{(10^{100})}. You have come shopping at a mall and are now buying a takoyaki machine with a value of N. (Takoyaki is the name of a Japanese snack.)

To make the payment, you will choose some amount of money which is at least N and give it to the clerk. Then, the clerk gives you back the change, which is the amount of money you give minus N.

What will be the minimum possible number of total banknotes used by you and the clerk, when both choose the combination of banknotes to minimize this count?

Assume that you have sufficient numbers of banknotes, and so does the clerk.

Constraints

N is an integer between 1 and 10^{1,000,000} (inclusive).

Input

Input is given from Standard Input in the following format:

N

Output

Print the minimum possible number of total banknotes used by you and the clerk.

Sample Input 1

36

Sample Output 1

8

If you give four banknotes of value 10 each, and the clerk gives you back four banknotes of value 1 each, a total of eight banknotes are used.

The payment cannot be made with less than eight banknotes in total, so the answer is 8.

Sample Input 2

91

Sample Output 2

3

If you give two banknotes of value 100, 1, and the clerk gives you back one banknote of value 10, a total of three banknotes are used.

Sample Input 3

314159265358979323846264338327950288419716939937551058209749445923078164062862089986280348253421170

Sample Output 3

243

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using static Exter;
using System.Linq;
using System.Numerics;
#if DEBUG
#else
using console = System.Console;
#endif

public class App
{
    public static void Main(string[] args)
    {
        string s = console.ReadLine();
        int[,] a = new int[s.Length+1,2];
        {
            int v = s[s.Length-1] - '0';
            a[s.Length-1,0] = v;
            a[s.Length-1,1] = 10 - v;
        }
        for(int i = s.Length-2;i>=0;i--)
        {
            int v = s[i] - '0';
            a[i,0] = Min(a[i+1,0] + v,a[i+1,1] + (v+1));
            a[i,1] = Min(a[i+1,0] + 10 - v,a[i+1,1] + 9 - v);
        }
        
        cout = Min(a[0,0],a[0,1]+1);
    }
    public string[] SnRead(int n)
    {
        var v = new string[n];
        for(int i = 0;i<n;i++)
            v[i] = console.ReadLine();
        return v;
    }
    public char[,] RectCharRead(int h,int w)
    {
        var v = new char[h,w];
        for(int i = 0;i < h;i++)
        {
            var s = console.ReadLine();
            for(int j = 0;j < w;j++)
            {
                v[i,j] = s[j];
            }
        }
        return v;
    }
    public bool[,] RectCharToBool(int h,int w)
    {
        var v = new bool[h,w];
        for(int i = 0;i < h;i++)
        {
            var s = console.ReadLine();
            for(int j = 0;j < w;j++)
            {
                v[i,j] = s[j] == '.';
            }
        }
        return v;
    }
    public class BiasedArray<Type>
    {
        private Type[] ContainedValue;
        public bool ReturnDefaultIfOutOfRange = true;
        public bool IgnoreSetIfOutOfRange = true;
        public Type DefaultValue = default(Type);
        public int Length;
        BiasedArray(int length)
        {
            Length = length;
            ContainedValue = new Type[length];
        }
        public bool IsWithinRange(int x)=>0<=x&&x<Length;
        public Type this[int x]
        {
            get
            {
                if(IsWithinRange(x))
                    return ContainedValue[x];
                else if(ReturnDefaultIfOutOfRange)
                    return DefaultValue;
                else
                    throw new IndexOutOfRangeException();
            }
            set
            {
                if(IsWithinRange(x))
                    ContainedValue[x] = value;
                else if(!IgnoreSetIfOutOfRange)
                    throw new IndexOutOfRangeException();
            }
        }
    }
    public class BiasedArray2<Type>
    {
        private Type[,] ContainedValue;
        public bool ReturnDefaultIfOutOfRange = true;
        public bool IgnoreSetIfOutOfRange = true;
        public Type DefaultValue = default(Type);
        public int Width;
        public int Height;
        BiasedArray2(int width,int height)
        {
            Width = width;
            Height = height;
            ContainedValue = new Type[width,height];
        }
        public bool IsWithinRange(int x,int y)=>0<=x&&x<Width&&0<=y&&y<Height;
        public Type this[int x,int y]
        {
            get
            {
                if(IsWithinRange(x,y))
                    return ContainedValue[x,y];
                else if(ReturnDefaultIfOutOfRange)
                    return DefaultValue;
                else
                    throw new IndexOutOfRangeException();
            }
            set
            {
                if(IsWithinRange(x,y))
                    ContainedValue[x,y] = value;
                else if(!IgnoreSetIfOutOfRange)
                    throw new IndexOutOfRangeException();
            }
        }
    }
    public class BiasedArray3<Type>
    {
        private Type[,,] ContainedValue;
        public bool ReturnDefaultIfOutOfRange = true;
        public bool IgnoreSetIfOutOfRange = true;
        public Type DefaultValue = default(Type);
        public int Width;
        public int Depth;
        public int Height;
        BiasedArray3(int width,int depth,int height)
        {
            Width = width;
            Depth = depth;
            Height = height;
            ContainedValue = new Type[width,depth,height];
        }
        public bool IsWithinRange(int x,int y,int z)=>0<=x&&x<Width&&0<=y&&y<Depth&&0<=z&&z<Height;
        public Type this[int x,int y,int z]
        {
            get
            {
                if(IsWithinRange(x,y,z))
                    return ContainedValue[x,y,z];
                else if(ReturnDefaultIfOutOfRange)
                    return DefaultValue;
                else
                    throw new IndexOutOfRangeException();
            }
            set
            {
                if(IsWithinRange(x,y,z))
                    ContainedValue[x,y,z] = value;
                else if(!IgnoreSetIfOutOfRange)
                    throw new IndexOutOfRangeException();
            }
        }
    }
    public static long Lcm(long a, long b)=>a*b/Gcd(a,b);
    public static long Gcd(long a, long b)=>a > b ? GcdRecursive(a, b) : GcdRecursive(b, a);
    private static long GcdRecursive(long a, long b){if(b == 0) return a; return GcdRecursive(b, a % b);}
}
public class RollingHash
{
    long[] h;
    long m = 2147483647;
    int b = 524287;
    Power baser;
    public RollingHash(string s)
    {
        baser = new Power(b);
        h = new long[s.Length];
        h[0] = 0;
        for(int i = 1;i < s.Length;i++)
        {
            h[i] = (h[i-1] * b + s[i]) % m;
        }
    }
    public long Calc(int l,int r)
    {
        cout = h[r];
        cout = h[l] * baser.GetEntry(r-l-1);
        return 0;
    }
}
public class PriorityQueue<T> : IEnumerable<T> where T : IComparable
        {
            List<T> buffer = new List<T>();
            static void PushHeap(List<T> array, T elem)
            {
                int n = array.Count;
                array.Add(elem);
 
                while (n != 0)
                {
                    int i = (n - 1) / 2;
                    if (array[n].CompareTo(array[i]) < 0)
                    {
                        T tmp = array[n]; array[n] = array[i]; array[i] = tmp;
                    }
                    n = i;
                }
            }
            static void PopHeap(List<T> array)
            {
                int n = array.Count - 1;
                array[0] = array[n];
                array.RemoveAt(array.Count - 1);
 
                for (int i = 0, j; (j = 2 * i + 1) < n;)
                {
                    if ((j != n - 1) && (array[j].CompareTo(array[j + 1]) > 0))
                        j++;
                    if (array[i].CompareTo(array[j]) > 0)
                    {
                        T tmp = array[j]; array[j] = array[i]; array[i] = tmp;
                    }
                    i = j;
                }
            }
            public int Count
            {
                get
                {
                    return buffer.Count;
                }
            }
            public void Push(T elem)
            {
                PushHeap(this.buffer, elem);
            }
            public T Peek()
            {
                return buffer[0];
            }
 
            public T Pop()
            {
                T a = buffer[0];
                PopHeap(this.buffer);
                return a;
            }
            public IEnumerator<T> GetEnumerator()
            {
                var v = new List<T>(buffer);
                while(v.Count != 0)
                {
                    yield return v[0];
                    PopHeap(v);
                }
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
        }
public class Power
    {
        public int Base;
        private List<long> Value = new List<long>();
        public Power(int v)
        {
            if(v==1)
                new ArgumentOutOfRangeException();
            long prev = -1;
            long g = v;
            Base = v;
            
            while(g > prev)
            {
                Value.Add(g);
                prev = g;
                g *= g;
            }
        }
        public long GetEntry(int exponent)
        {
            long s = 1;
            for(int i = 0;(1<<i)<=exponent;i++)
            {
                if((exponent & (1<<i)) != 0)
                {
                    s *= Value[i];
                }
            }
            return s;
        }
    }
public static class Exter
{
    public static IEnumerable<long> PrimeFactors(long n)
    {
        int i = 2;
        long tmp = n;

        while (i * i <= n)
        {
            if(tmp % i == 0){
                tmp /= i;
                yield return i;
            }else{
                i++;
            }
        }
        if(tmp != 1) yield return tmp;
    }
    public class LoopArray<T>
    {
        public readonly int Length;
        private T[] arr;
        public LoopArray(int Capacity)
        {
            Length = Capacity;
        }
        public LoopArray(T[] ar)
        {
            arr = new T[ar.Length];
            Array.Copy(ar,arr,ar.Length);
        }
    }
    public class Point
    {
        public Point(long cx, long cy)
        {
            x = cx;
            y = cy;
        }
        public long x;
        public long y;
    }
    public static IEnumerable<Result> ListAll<T1,T2,Result>(IEnumerable<T1> a,IEnumerable<T2> b,Func<T1,T2,Result> f)
    {
        foreach(var v in a)
        {
            foreach(var w in b)
               yield return f(v,w);
        }
    }
    public static IEnumerable<Result> ListAll<T1,T2,Result>(IEnumerable<T1> a,IEnumerable<T2> b,Func<T1,T2,Result> f,Func<T1,T2,bool> s)
    {
        foreach(var v in a)
        {
            foreach(var w in b)
               if(s(v,w)) yield return f(v,w);
        }
    }
    public static int ToInt(this long v)=>(int)v;
    public static int ToInt(this string v)=>int.Parse(v);
    public static int Max(params int[] p)=>p.Max();
    public static long Max(params long[] p)=>p.Max();
    public static int Min(params int[] p)=>p.Min();
    public static long Min(params long[] p)=>p.Min();
    public static int Gcd(int a, int b)=>a > b ? GcdRecursive(a, b) : GcdRecursive(b, a);
    private static int GcdRecursive(int a, int b)=>b == 0 ? a : GcdRecursive(b, a % b);
    public static object cout
    {
        set
        {
            console.Write(value.ToString());
            console.WriteLine();
            
        }
    }
    public static void ToCout<t>(this IEnumerable<t> v)
    {
        cout = string.Join(",",v);
    }
    public static int[] readarr
    {
        get 
        {
            preadarr = console.ReadLine().Split().Select(s=>int.Parse(s)).ToArray();
            return preadarr;
        }
    }
    public static int[] preadarr;
}


#if DEBUG
public static class console
{
    static int cursorLine = 0;
    static readonly string[] cin = System.IO.File.ReadAllLines("Input.txt");
    static public string ReadLine()
    { 
        if(cursorLine == cin.Length)
            cout = "Out";
        return cin[cursorLine++];
    }
    static public void WriteLine()
    {
        Console.WriteLine();
    }
    static public void WriteLine<T>(T input)
    {
        Console.WriteLine(input);
    }
    static public void Write<T>(T input)
    {
        Console.Write(input);
    }
    static public void WriteLine(string s,params object[] arr)
    {
        Console.WriteLine(s,arr);
    }
}
#endif