package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
nextInt := func() int {
scanner.Scan()
x, _ := strconv.Atoi(scanner.Text())
return x
}
T := nextInt()
for t := 0; t < T; t++ {
N, M := nextInt(), nextInt()
grid := make([][]int, N)
for i := 0; i < N; i++ {
grid[i] = make([]int, M)
for j := 0; j < M; j++ {
grid[i][j] = nextInt()
}
}
// 访问数组,记录哪些格子已被选
visited := make([][]bool, N)
for i := range visited {
visited[i] = make([]bool, M)
}
var maxSum int = 0
// DFS 函数:从 (i, j) 开始搜索
var dfs func(i, j, sum int)
dfs = func(i, j, sum int) {
// 判断是否到达最后一行或列
if i == N {
if sum > maxSum {
maxSum = sum
}
return
}
nextI, nextJ := i, j+1
if nextJ == M {
nextI, nextJ = i+1, 0
}
// 选项1:不选当前格子
dfs(nextI, nextJ, sum)
// 选项2:选当前格子(如果合法)
if !visited[i][j] {
// 检查周围 8 个方向是否有已选的格子
valid := true
dx := []int{-1, -1, -1, 0, 0, 0, 1, 1, 1}
dy := []int{-1, 0, 1, -1, 0, 1, -1, 0, 1}
for k := 0; k < 9; k++ {
ni, nj := i+dx[k], j+dy[k]
if ni >= 0 && ni < N && nj >= 0 && nj < M && visited[ni][nj] {
valid = false
break
}
}
if valid {
visited[i][j] = true
dfs(nextI, nextJ, sum+grid[i][j])
visited[i][j] = false // 回溯
}
}
}
dfs(0, 0, 0)
fmt.Println(maxSum)
}
}