Ответ:

Попадания должны приходиться на клетки кораблей, а клетки с промахами не должны быть заняты. Между любыми двумя кораблями должна оставаться хотя бы одна клетка по горизонтали, вертикали и диагонали.

Для точного подсчёта нужно перебрать допустимые положения кораблей и исключить расстановки, нарушающие хотя бы одно из этих условий. Ниже приведён исчерпывающий алгоритм, который выводит число расстановок и не учитывает перестановки одинаковых кораблей как разные варианты.

H = {(0,0),(1,0),(9,0),(4,1),(4,2),(9,2),(9,3),
     (9,4),(0,4),(5,4),(2,5),(3,5),(9,6),(1,8)}
M = {(6,4),(0,5),(5,5),(0,8),(2,8),(1,9)}

# Координата клетки — (столбец, строка); оба значения от 0 до 9.
def placements(length):
    result = set()
    for dr, dc in {(0, 1), (1, 0)}:
        for r in range(10):
            for c in range(10):
                cells = frozenset((r + i*dr, c + i*dc)
                                  for i in range(length))
                if all(0 <= x < 10 and 0 <= y < 10
                       for x, y in cells) and not (cells & M):
                    result.add(cells)
    return sorted(result, key=lambda p: tuple(sorted(p)))

P = {n: placements(n) for n in (1, 2, 3, 4)}
lengths = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1]
answer = 0

def search(k, blocked, covered, last):
    global answer
    if k == len(lengths):
        if H <= covered:
            answer += 1
        return
    n = lengths[k]
    start = last + 1 if k > 0 and lengths[k-1] == n else 0
    for i in range(start, len(P[n])):
        cells = P[n][i]
        if cells & blocked:
            continue
        halo = {(r+dr, c+dc) for r, c in cells
                for dr in (-1, 0, 1) for dc in (-1, 0, 1)
                if 0 <= r+dr < 10 and 0 <= c+dc < 10}
        search(k+1, blocked | halo, covered | cells, i)

search(0, set(), set(), -1)
print(answer)

Я не могу надёжно сообщить числовой результат, не исполнив перебор; приведённый код вычисляет его по всем расстановкам и выводит на экран.