Validating a Battleship board
JavaScript (ES6),  162  158 bytes
Returns 0 if the grid is invalid, or a positive integer otherwise.

m=&gt;(o=0,g=u=&gt;m.some((r,y)=&gt;r.some((v,x)=&gt;v&amp;&amp;[0,1].map(d=&gt;(r=(w,X=x+!d*w,R=m[y+d*w]||0)=&gt;R[X]&amp;&amp;R[R[X]--,u&amp;(k=1&lt;&lt;w*3)*7&amp;&amp;g(u-k),r(-~w),X]++)``)))|u||++o)(668)*o

Try it online!
Commented
m =&gt; (                       // m[] = input matrix
  o = 0,                     // o = result
  g = u =&gt;                   // g is a recursive function taking a bit mask u
                             // holding the ship counters on 4 x 3 bits
  m.some((r, y) =&gt;           //   for each row r[] at position y in m[]:
    r.some((v, x) =&gt;         //     for each value v at position x in r[]:
      v &amp;&amp;                   //       abort if v is not set
      [0, 1].map(d =&gt;        //       otherwise, look for a horizontal ship (d = 0)
        (                    //       or a vertical ship (d = 1):
          r = (              //         r is a recursive function taking:
            w,               //           w = ship width - 1
            X = x + !d * w,  //           X = position of the cell in ...
            R = m[y + d * w] //           ... R[] = row of the cell
                || 0         //           (force it to 0 if undefined)
          ) =&gt;               //
          R[X] &amp;&amp;            //           abort if R[X] is not set
          R[                 //
            R[X]--,          //           otherwise, set the cell to 0
            u &amp; 7 *          //           if there's still at least one ship of
            (k = 1 &lt;&lt; w * 3) //           width w to be found in the grid:
            &amp;&amp; g(u - k),     //             do a recursive call to g with u updated
            r(-~w),          //           do a recursive call to r with w + 1
            X                //
          ]++                //           restore the cell afterwards
        )``                  //         initial call to r with u zero'ish
      )                      //       end of map()
    )                        //     end of some()
  )                          //   end of some()
  | u || ++o                 //   increment o if the grid has been cleared and all
                             //   boats have been found
)(668)                       // initial call to g with u = 668 (001 010 011 100)
* o                          // multiply by o