Minimal cost path in wall-breaking maze
JavaScript (ES7),  198 185 179  178 bytes
Expects a matrix of integers with -1 for a wall and 0 for an empty cell. Returns a matrix of Boolean values.

m=&gt;(g=(Y,w,n,X)=&gt;w&gt;=W&amp;&amp;w&gt;W|n&gt;N?0:m[Y+1]||1/m[Y][X+1]?m.map((r,y)=&gt;r.map((v,x)=&gt;v&gt;0?1:(X-x)**2+(Y-y)**2^1?0:r[r[x]=1,g(y,w-v,-~n,x),x]=v)):o=g(-1,W=w,N=n))(0,0,W=++m[0][0]/0,0)&amp;&amp;o

Try it online!
Commented
This is a depth-first search. Visited cells are marked with 1. We keep track of the number of broken walls in w and the total number of visited cells in n. We abort as soon as the current path is worse than the best path found so far.
m =&gt; (                         // m[] = input matrix
  g = (                        // g is a recursive function taking:
    Y, w, n, X                 //   (X, Y) = current position
                               //   w = number of broken walls
  ) =&gt;                         //   n = number of visited cells
  w &gt;= W &amp;&amp; w &gt; W | n &gt; N ?    // if (w, n) is worse than (W, N):
    0                          //   abort
  :                            // else:
    m[Y + 1] ||                //   if there's a cell below the current cell
    1 / m[Y][X + 1] ?          //   or a cell on the right:
      m.map((r, y) =&gt;          //     for each row r[] at position y in m[]:
        r.map((v, x) =&gt;        //       for each value v at position x in r[]:
          v &gt; 0 ?              //         if v is positive:
            1                  //           yield 1
          :                    //         else:
            (X - x) ** 2 +     //           if the squared distance between
            (Y - y) ** 2 ^ 1 ? //           (X, Y) and (x, y) is not equal to 1:
              0                //             do nothing
            :                  //           else:
              r[r[x] = 1,      //             mark r[x] as visited by setting it to 1
                g(y, w - v,    //             do a recursive call at (x, y) with n+1
                  -~n, x),     //             if v = -1, w is also incremented
                x              //             actual index ...
              ] = v            //             ... to restore r[x] to v afterwards
        )                      //       end of inner map()
      )                        //     end of outer map()
    :                          //   else (bottom-right cell):
      o = g(-1, W = w, N = n)  //     update (W, N) and use a last recursive call
                               //     with X undefined and Y=-1 to build the output o
)(0, 0, W = ++m[0][0] / 0, 0)  // initial call to g at (0, 0); set the cell at (0, 0)
                               // to 1 and set W to +inf
&amp;&amp; o                           // return o

The purpose of the last recursive call o = g(-1, W = w, N = n) is to create a copy of the current maze where all visited cells are marked with true and all other cells are marked with false.
For this call, it's important to notice that:

because W = w and N = n, the abort test is always false
because Y = -1, the test on m[Y + 1] is always true
because X is undefined, the squared distance is always NaN

Therefore, what is actually done is simply:
m.map((r, y) =&gt; r.map((v, x) =&gt; v &gt; 0 ? 1 : 0))