import java.util.*

fun main(args: Array<String>) = AGC043A.main()

object AGC043A {
    fun readInt() = readLine()!!.toInt()
    fun readInts() = readLine()!!.split(" ").map { it.toInt() }

    val width: Int
    val height: Int
    val grid: Grid<Boolean> // is white
    val flipsGrid: Grid<Int>

    init {
        val (h, w) = readInts()
        val rows = (1..h).map { readLine()!!.map { (it == '.') } }
        width = w
        height = h
        grid = Grid(rows)
        CellNode.field = grid
        flipsGrid = grid.map { Int.MAX_VALUE }
    }

    fun main() {
        //println(grid)
        val good = grid.mapIndexed { x, y, it ->
            (x == width - 1 && y == height - 1 && it)
        }
        val start = grid.get(width - 1, height - 1)

        val root = if (start == true) CellNode(width - 1, height - 1)
        else CellNode(Dim2(width - 1, height - 1), flips = 1, friendColor = false)

        DepthFirstSearch<Dim2>().search(root)
            .filterIsInstance<CellNode>()
            .forEach {
                if (flipsGrid.get(it.x, it.y) > it.flips) flipsGrid.set(it.value.x, it.value.y, it.flips)
            }
        //println("flips:")
        //println(flipsGrid)

        val result = flipsGrid.get(0, 0)
        println((result + 1) / 2)
    }


    fun Grid<Boolean>.flip(x1: Int, y1: Int, x2: Int, y2: Int) {
        this.mapIndexed { x, y, it ->
            if (x in x1 - 1 until x2 && y in y1 - 1 until y2) this.set(x, y, !it)
        }
    }

    data class Dim2(val x: Int, val y: Int) {
        override fun toString(): String = "($x,$y)"
    }

    class CellNode(
        override val value: Dim2,
        val flips: Int = 0,  // 白黒をまたぐ回数
        val friendColor: Boolean = true // 通れる色
    ) :
        TreeNode<Dim2> {
        companion object {
            lateinit var field: Grid<Boolean>

        }

        constructor(x: Int, y: Int) : this(Dim2(x, y))

        val x: Int get() = value.x
        val y: Int get() = value.y
        fun exists(): Boolean {
            return (x in 0 until field.width) &&
                    (y in 0 until field.height) &&
                    field.get(x, y) == friendColor
        }

        private fun exists(x: Int, y: Int): Boolean {
            return (x in 0 until field.width) &&
                    (y in 0 until field.height) &&
                    field.get(x, y) == friendColor
        }

        private fun childTo(x: Int, y: Int): CellNode {
            return if (exists(x, y)) CellNode(Dim2(x, y), flips, friendColor)
            else CellNode(Dim2(x, y), flips + 1, !friendColor)
        }

        override val children: Sequence<TreeNode<Dim2>>
            get() = sequenceOf(
                childTo(x - 1, y),
                childTo(x, y - 1)
            ).filter {
                (it.x in 0 until Companion.field.width) && (it.y in 0 until Companion.field.height)
            }

        override fun toString(): String = "$value: $flips : $friendColor"
    }

    class Grid<T>(rows: List<List<T>>) {
        val width: Int
            get() = rows.first().size
        val height: Int
            get() = rows.size
        private val rows: List<MutableList<T>> = rows.map { it.toMutableList() }
        fun get(x: Int, y: Int): T = rows[y][x]
        fun set(x: Int, y: Int, value: T) {
            rows[y][x] = value
        }

        fun <R> map(transform: (T) -> R): Grid<R> =
            Grid(
                rows = rows.map { it.map(transform) }
            )

        fun <R> mapIndexed(transform: (x: Int, y: Int, T) -> R): Grid<R> =
            Grid(
                rows = rows.mapIndexed { y, it ->
                    it.mapIndexed { x, it ->
                        transform(x, y, it)
                    }
                }
            )

        fun flatten(): List<T> = rows.flatten()

        override fun toString(): String {
            return rows.joinToString("\n") { it.joinToString(" ") }
        }
    }

    interface TreeNode<T> {
        val value: T
        val children: Sequence<TreeNode<T>>
    }

    interface TreeSearch<T> {
        fun search(root: TreeNode<T>): Sequence<TreeNode<T>>
    }

    abstract class TreeSearchBase<T : Any> : TreeSearch<T> {
        private val visited = mutableSetOf<Any>()
        protected fun TreeNode<T>.isNotVisited(): Boolean {
            val it = this as CellNode
            val prevFlips = flipsGrid.get(it.x, it.y)
            return prevFlips > this.flips
            //!visited.contains(this.value)
        }

        protected fun TreeNode<T>.markVisited() {
            visited.add(this.value)
        }
    }

    class DepthFirstSearch<T : Any> : TreeSearchBase<T>() {
        private val stack = LinkedList<TreeNode<T>>()
        private fun push(node: TreeNode<T>) {
            stack.addFirst(node)
            node.markVisited()
        }

        private fun pop(): TreeNode<T>? {
            val first: TreeNode<T>? = stack.first
            if (first != null) stack.removeFirst()
            return first
        }

        override fun search(root: TreeNode<T>): Sequence<TreeNode<T>> {
            if (root.isNotVisited()) push(root)
            return searchAll()
        }

        private fun searchAll(): Sequence<TreeNode<T>> = generateSequence {
            if (stack.isNotEmpty()) {
                val first = pop()!!
                first.children.filter { it.isNotVisited() }.forEach { push(it) }
                first
            } else null
        }
    }
}

Measured memory_bytes: 71500