You are given a chessboard of size NxN. There is a white knight and several black pawns located on the board. The knight can move similarly to the normal knight in the game of chess; however it can only move towards the right of the board (see the below figure).

The mission of the knight is to capture as many black pawns as possible. Its journey ends when it moves to the rightmost column of the board.
Compute the maximum number of black pawns the white knight can capture.

------ Input ------ 

The first line contains t, the number of test cases (about 10). Then t test cases follow.
Each test case has the following form:
The first line contains N, the size of the chessboard (4 ≤ N ≤ 1000).
Then N lines follow, each line containing N characters which may be '.', 'K' or 'P', corresponding to the empty cell, the white knight, and the black pawn, respectively. There is exactly one 'K' character in the whole of the board.

------ Output ------ 

For each test case, print in a single line the maximum number of black pawns that can be captured.

----- Sample Input 1 ------ 
1
5
K....
..P..
.P...
...P.
.....
----- Sample Output 1 ------ 
2

Source: codechef | Difficulty: MEDIUM
Tags: Dynamic programming


Solutions:
t = int(input())

def maxpawns(x, y, n):
	if x >= n or x < 0 or y >= n:
		return 0
	if values[y][x] != -1:
		return values[y][x]
	values[y][x] = board[x][y] + max(maxpawns(x - 1, y + 2, n), maxpawns(x + 1, y + 2, n), maxpawns(x + 2, y + 1, n), maxpawns(x - 2, y + 1, n))
	return values[y][x]
for abcd in range(t):
	n = int(input())
	board = [list(input()) for jkl in range(n)]
	values = [[-1] * n for mno in range(n)]
	for i in range(n):
		for j in range(n):
			if board[i][j] == 'K':
				(x1, y1) = (i, j)
				board[i][j] = 0
			if board[i][j] == 'P':
				board[i][j] = 1
			if board[i][j] == '.':
				board[i][j] = 0
	print(maxpawns(x1, y1, n))


def getMax(boardSize, board, i, j, dp):
	if i < 0:
		return 0
	elif i >= boardSize or j >= boardSize:
		return 0
	elif dp[i][j] != None:
		return dp[i][j]
	else:
		if board[i][j] == 'P':
			dp[i][j] = 1 + max(getMax(boardSize, board, i + 1, j + 2, dp), getMax(boardSize, board, i + 2, j + 1, dp), getMax(boardSize, board, i - 1, j + 2, dp), getMax(boardSize, board, i - 2, j + 1, dp))
		else:
			dp[i][j] = max(getMax(boardSize, board, i + 1, j + 2, dp), getMax(boardSize, board, i + 2, j + 1, dp), getMax(boardSize, board, i - 1, j + 2, dp), getMax(boardSize, board, i - 2, j + 1, dp))
		return dp[i][j]
testCases = int(input())
result = []
for case in range(testCases):
	boardSize = int(input())
	board = []
	knightPosition_i = 0
	knightPosition_j = 0
	for j in range(boardSize):
		boardRow = []
		row = input()
		for index in range(len(row)):
			if row[index] == 'K':
				knightPosition_i = j
				knightPosition_j = index
			boardRow.append(row[index])
		board.append(boardRow)
	dp = []
	for i in range(boardSize):
		dp_row = []
		for j in range(boardSize):
			dp_row.append(None)
		dp.append(dp_row)
	result.append(getMax(boardSize, board, knightPosition_i, knightPosition_j, dp))
for r in result:
	print(r)


from collections import defaultdict
get_int = lambda : int(input())
get_mint = lambda : list(map(int, input().split()))
knight_moves = [[1, 2], [1, -2], [2, 1], [2, -1]]

def recur(x, y):
	if x >= N or y >= N or x < 0 or (y < 0):
		return 0
	if dp[x][y] != -1:
		return dp[x][y]
	cnt = 1 if chessboard[x][y] == 'P' else 0
	dp[x][y] = max(cnt + recur(x + 1, y + 2), cnt + recur(x + 2, y + 1), cnt + recur(x - 2, y + 1), cnt + recur(x - 1, y + 2))
	return dp[x][y]
for _ in range(get_int()):
	N = get_int()
	chessboard = [input() for _ in range(N)]
	dp = [[-1 for _ in range(N)] for _ in range(N)]
	for row in range(N):
		for cell in range(N):
			if chessboard[row][cell] == 'K':
				(r, c) = (row, cell)
				break
	print(max(recur(r + 1, c + 2), recur(r + 2, c + 1), recur(r - 2, c + 1), recur(r - 1, c + 2)))


for _ in range(int(input())):
	n = int(input())
	chess = [list(input()) for i in range(n)]
	dp = [[-1] * n for _ in range(n)]

	def helper(r, c):
		if r < 0 or c < 0 or r >= n or (c >= n):
			return 0
		if c == n - 1:
			if chess[r][c] == 'P':
				return 1
			else:
				return 0
		if dp[r][c] != -1:
			return dp[r][c]
		if chess[r][c] == 'P':
			ans = 1
		else:
			ans = 0
		dp[r][c] = ans + max(helper(r - 2, c + 1), helper(r - 1, c + 2), helper(r + 1, c + 2), helper(r + 2, c + 1))
		return dp[r][c]
	for i in range(n):
		for j in range(n):
			if chess[i][j] == 'K':
				print(helper(i, j))
				break


def solve(i, j):
	if i >= n or j >= n or i < 0 or (j < 0):
		return 0
	if dp[i][j] != -1:
		return dp[i][j]
	cur_val = 0
	if mat[i][j] == 'P':
		cur_val = 1
	cnt = cur_val + max(solve(i - 1, j + 2), solve(i - 2, j + 1), solve(i + 1, j + 2), solve(i + 2, j + 1))
	dp[i][j] = cnt
	return dp[i][j]
for _ in range(int(input())):
	n = int(input())
	mat = list()
	for i in range(n):
		mat.append(input())
	(row, col) = (-1, -1)
	dp = [[-1] * n for i in range(n)]
	for i in range(n):
		for j in range(n):
			if mat[i][j] == 'K':
				(row, col) = (i, j)
				break
	(i, j) = (row, col)
	print(max(solve(i - 2, j + 1), solve(i - 1, j + 2), solve(i + 1, j + 2), solve(i + 2, j + 1)))


import sys
sys.setrecursionlimit(5000)

def fun_dp(x, y):
	if x >= n or x < 0 or y < 0 or (y >= n):
		cache[x][y] = 0
		return 0
	if cache[x][y] != -1:
		return cache[x][y]
	else:
		c1 = fun_dp(x + 1, y + 2)
		c2 = fun_dp(x + 2, y + 1)
		c3 = fun_dp(x - 1, y + 2)
		c4 = fun_dp(x - 2, y + 1)
		temp = max(c1, c2, c3, c4, 0)
		if mat[x][y] == 'P':
			cache[x][y] = temp + 1
		else:
			cache[x][y] = temp
		return cache[x][y]

def solve(i, j):
	if i >= n or j >= n or i < 0 or (j < 0):
		return 0
	if dp[i][j] != -1:
		return dp[i][j]
	cur_val = 0
	if mat[i][j] == 'P':
		cur_val = 1
	cnt = cur_val + max(solve(i - 1, j + 2), solve(i - 2, j + 1), solve(i + 1, j + 2), solve(i + 2, j + 1))
	dp[i][j] = cnt
	return dp[i][j]
test = int(input())
while test:
	n = int(sys.stdin.readline().rstrip('\n'))
	mat = []
	found = False
	ind = [0, 0]
	for i in range(n):
		temp = sys.stdin.readline().rstrip('\n')
		if not found:
			for j in range(n):
				if temp[j] == 'K':
					ind = [j, i]
					found = True
		mat.append(temp)
	cache = [[-1 for _ in range(n + 6)] for k in range(n + 6)]
	print(fun_dp(ind[1], ind[0]))
	test -= 1


def dp(i, j):
	if j >= n or i >= n or i < 0:
		return 0
	if memo[i][j] != -1:
		return memo[i][j]
	if c[i][j] == 'P':
		P = 1
	else:
		P = 0
	memo[i][j] = max(P + dp(i + 1, j + 2), P + dp(i + 2, j + 1), P + dp(i - 2, j + 1), P + dp(i - 1, j + 2))
	return memo[i][j]
for k in range(int(input())):
	n = int(input())
	memo = [[-1 for i in range(n)] for j in range(n)]
	c = [input() for j in range(n)]
	for j in range(n):
		pos = c[j].find('K')
		if pos >= 0:
			row = j
			break
	col = pos
	print(max(dp(row + 1, col + 2), dp(row + 2, col + 1), dp(row - 2, col + 1), dp(row - 1, col + 2)))


def knight(k_r, k_c, n):
	for j in range(n - 2, k_c - 1, -1):
		for i in range(n):
			a = b = c = d = 0
			if i - 2 >= 0 and j + 1 < n:
				a = dp[i - 2][j + 1]
			if i - 1 >= 0 and j + 2 < n:
				b = dp[i - 1][j + 2]
			if i + 2 < n and j + 1 < n:
				c = dp[i + 2][j + 1]
			if i + 1 < n and j + 2 < n:
				d = dp[i + 1][j + 2]
			dp[i][j] += max(a, b, c, d)
	return dp[k_r][k_c]
T = int(input())
for t in range(T):
	n = int(input())
	arr = []
	dp = []
	for i in range(n):
		s1 = input()
		l1 = [0] * n
		for j in range(n):
			if s1[j] == 'K':
				k_r = i
				k_c = j
			if s1[j] == 'P':
				l1[j] = 1
		arr.append(s1)
		dp.append(l1)
	print(knight(k_r, k_c, n))


def main():
	t = int(input())
	for i in range(t):
		n = int(input())
		ploc = []
		kloc = (0, 0)
		append = ploc.append
		for j in range(n):
			line = input()
			for (k, c) in enumerate(line):
				if c == 'K':
					kloc = (j, k)
				if c == 'P':
					append((j, k))
		solve(kloc, ploc, n)

def solve(kloc, ploc, n):
	cache = [[0] * n for i in range(n)]
	(y, x) = kloc
	for loc in ploc:
		cache[loc[0]][loc[1]] = 1
	for j in range(n - 2, x - 1, -1):
		for i in range(n):
			(a, b, c, d) = (0, 0, 0, 0)
			if 0 <= i - 1 < n and j + 2 < n:
				a = cache[i - 1][j + 2]
			if 0 <= i + 1 < n and j + 2 < n:
				b = cache[i + 1][j + 2]
			if 0 <= i - 2 < n and j + 1 < n:
				c = cache[i - 2][j + 1]
			if 0 <= i + 2 < n and j + 1 < n:
				d = cache[i + 2][j + 1]
			cache[i][j] += max(a, b, c, d)
	print(cache[y][x])
main()


def calculate_max_captured(size, knight_position, pawn_positions):
	cancel = -10 ** 6
	pre_previous = [cancel] * size
	previous = [cancel] * size
	previous[knight_position[1]] = 0
	current = [cancel] * size
	for i in range(knight_position[0] + 1, size):
		for j in range(size):
			max_captured = cancel
			if 0 <= j + 2 < size and max_captured < previous[j + 2]:
				max_captured = previous[j + 2]
			if 0 <= j - 2 < size and max_captured < previous[j - 2]:
				max_captured = previous[j - 2]
			if 0 <= j + 1 < size and max_captured < pre_previous[j + 1]:
				max_captured = pre_previous[j + 1]
			if 0 <= j - 1 < size and max_captured < pre_previous[j - 1]:
				max_captured = pre_previous[j - 1]
			if (i, j) in pawn_positions:
				max_captured += 1
			if max_captured > current[j]:
				current[j] = max_captured
		pre_previous = previous
		previous = current
		current = [cancel] * size
	return max(previous)
testcases = int(input())
for testcase in range(testcases):
	size = int(input())
	knight_position = None
	pawn_positions = set()
	for i in range(size):
		for (j, cell) in enumerate(input()):
			if cell == 'K':
				knight_position = (j, i)
			if cell == 'P':
				pawn_positions.add((j, i))
	max_captured = calculate_max_captured(size, knight_position, pawn_positions)
	print(max_captured)


sli = []

def exploreAll(r, c, n):
	if c >= n or r < 0 or r >= n:
		return 0
	if sli[c][r] != -1:
		return sli[c][r]
	sli[c][r] = arr[r][c] + max(exploreAll(r + 2, c + 1, n), exploreAll(r + 1, c + 2, n), exploreAll(r - 1, c + 2, n), exploreAll(r - 2, c + 1, n))
	return sli[c][r]
tn = int(input())
for _ in range(tn):
	n = int(input())
	sli = [[-1 for _ in range(n)] for _ in range(n)]
	arr = [list(input()) for _ in range(n)]
	(x, y) = (-1, -1)
	for i in range(n):
		for j in range(n):
			if arr[i][j] == 'K':
				(x, y) = (i, j)
			if arr[i][j] == 'P':
				arr[i][j] = 1
			else:
				arr[i][j] = 0
	a = exploreAll(x, y, n)
	print(a)


def jump(i, j):
	if i < 0 or j < 0 or i >= n or (j >= n):
		return 0
	if dp[i][j] != -1:
		return dp[i][j]
	dp[i][j] = 1 if board[i][j] == 'P' else 0
	dp[i][j] += max(jump(i - 1, j + 2), jump(i - 2, j + 1), jump(i + 1, j + 2), jump(i + 2, j + 1))
	return dp[i][j]
t = int(input())
for _ in range(t):
	n = int(input())
	board = [['.' for _ in range(n)] for _ in range(n)]
	for i in range(n):
		board[i] = list(input())
		if 'K' in board[i]:
			loc_k = (i, board[i].index('K'))
	dp = [[-1 for _ in range(n)] for _ in range(n)]
	print(jump(loc_k[0], loc_k[1]))


def calcPawns(i, j):
	if i < 0 or j < 0 or i >= n or (j >= n):
		return 0
	if dp[i][j] != -1:
		return dp[i][j]
	dp[i][j] = 1 if board[i][j] == 'P' else 0
	dp[i][j] += max(calcPawns(i - 1, j + 2), calcPawns(i - 2, j + 1), calcPawns(i + 1, j + 2), calcPawns(i + 2, j + 1))
	return dp[i][j]
n = 0
board = [[]]
dp = [[-1 for j in range(n)] for i in range(n)]
T = int(input())
for t in range(T):
	n = int(input())
	board = [list(input()) for _ in range(n)]
	dp = [[-1 for j in range(n)] for i in range(n)]
	(ki, kj) = (0, 0)
	for i in range(n):
		for j in range(n):
			if board[i][j] == 'K':
				(ki, kj) = (i, j)
				break
	print(calcPawns(ki, kj))


def recur(dp, matrix, i, j, n, m):
	if i >= 0 and j >= 0 and (i < n) and (j < m):
		if dp[i][j] != -1:
			return dp[i][j]
		if matrix[i][j] == 'P':
			dp[i][j] = 1 + max(recur(dp, matrix, i - 1, j + 2, n, m), recur(dp, matrix, i + 1, j + 2, n, m), recur(dp, matrix, i - 2, j + 1, n, m), recur(dp, matrix, i + 2, j + 1, n, m))
		else:
			dp[i][j] = max(recur(dp, matrix, i - 1, j + 2, n, m), recur(dp, matrix, i + 1, j + 2, n, m), recur(dp, matrix, i - 2, j + 1, n, m), recur(dp, matrix, i + 2, j + 1, n, m))
		return dp[i][j]
	else:
		return 0
for _ in range(int(input())):
	n = int(input())
	board = []
	for _ in range(n):
		board.append(list(input()))
	dp = [[-1] * n for _ in range(n)]
	for i in range(n):
		for j in range(n):
			if board[i][j] == 'K':
				x = i
				y = j
				break
	print(recur(dp, board, x, y, n, n))


def computePawns(board, row, column, n, dp):
	if row < 0 or row > n - 1 or column > n - 1:
		return 0
	if dp[row][column] != -1:
		return dp[row][column]
	p = max(computePawns(board, row - 2, column + 1, n, dp), computePawns(board, row - 1, column + 2, n, dp), computePawns(board, row + 1, column + 2, n, dp), computePawns(board, row + 2, column + 1, n, dp))
	if board[row][column] == 'P':
		p += 1
	dp[row][column] = p
	return p
t = int(input())
for _ in range(t):
	n = int(input())
	b = False
	board = []
	dp = [[-1] * n for i in range(n)]
	for i in range(n):
		board.append(input())
	for i in range(n):
		for j in range(n):
			if board[i][j] == 'K':
				row = i
				column = j
				b = True
				break
		if b == True:
			break
	print(computePawns(board, row, column, n, dp))


def solve(i, j, dp, l, n):
	if i < 0 or i >= n or j < 0 or (j >= n):
		return 0
	if dp[i][j] != -1:
		return dp[i][j]
	if matrix[i][j] == 'P':
		p = 1
	else:
		p = 0
	dp[i][j] = max(solve(i + 2, j + 1, dp, l, n), solve(i + 1, j + 2, dp, l, n), solve(i - 1, j + 2, dp, l, n), solve(i - 2, j + 1, dp, l, n)) + p
	return dp[i][j]
for _ in range(int(input())):
	n = int(input())
	matrix = []
	for i in range(n):
		matrix.append(input())
	dp = [[-1] * n for _ in range(n)]
	for i in range(n):
		for j in range(len(matrix[0])):
			if matrix[i][j] == 'K':
				x = i
				y = j
				break
	print(solve(x, y, dp, matrix, n))