# DPでやる N, T = map(int, input().split()) A = [list(map(int, input().split())) for _ in range(N)] DP = [[[-1] * N for _ in range(N)] for _ in range(T)] DP_end = [[(-1,-1, -1) for _ in range(N)] for _ in range(N)] Pre = [[[(-1,-1,-1)] * N for _ in range(N)] for _ in range(T)] for i in range(N): for j in range(N): DP[0][i][j] = A[i][j] # DP[t][i][j]:=tターン目で、座標(i,j)にいて、i以降の座標には(i,j)を除いてどれも訪れてない時のスコアのMAX for t in range(T): for i in range(N): for j in range(N): if(DP[t][i][j] < 0): continue v = 0 for k in range(j - 1, -1, -1): v += A[i][k] # (i,k)まで行く。 nxt_t = t +abs(j - k) if(nxt_t < T): if(DP_end[i][k][1] < DP[t][i][j] + v): DP_end[i][k] = (nxt_t, DP[t][i][j] + v) # (i + 1,k)に行く。 nxt_t += 1 if(nxt_t < T): if(i < N - 1 and DP[nxt_t][i + 1][k] < DP[t][i][j] + v + A[i + 1][k]): DP[nxt_t][i + 1][k] = DP[t][i][j] + v + A[i + 1][k] Pre[nxt_t][i + 1][k ] = (t, i, j) v = 0 for k in range(j, N): if(k != j): v += A[i][k] # (i,k)まで行く。 nxt_t = t +abs(j - k) if(nxt_t < T): if(DP_end[i][k][1] < DP[t][i][j] + v): DP_end[i][k] = (nxt_t, DP[t][i][j] + v) # (i + 1,k)に行く。 nxt_t += 1 if(nxt_t < T): if(i < N - 1 and DP[nxt_t][i + 1][k] < DP[t][i][j] + v + A[i + 1][k]): DP[nxt_t][i + 1][k] = DP[t][i][j] + v + A[i + 1][k] Pre[nxt_t][i + 1][k ] = (t, i, j) best_i = -1 best_j = -1 best_t = -1 best_score = 0 for i in range(N): for j in range(N): if(DP_end[i][j][1] > best_score): best_i = i best_j = j best_t = DP_end[i][j][0] best_score = DP_end[i][j][1] # print(best_i,best_j) Ans = [(best_i, best_j)] i = best_i j = best_j t = best_t while True: nt, ni, nj = Pre[t][i][j] if(nt == -1): break # print(nt,ni,nj,t,i,j) if(ni == i - 1): if(j <= nj): for k in range(j, nj + 1): Ans.append((ni, k)) else: for k in range(j, nj - 1, -1): Ans.append((ni, k)) t,i,j = nt,ni,nj # (ni-1,nj)から(ni,j)に行き、(i,j)についた。 print(len(Ans)) for l in Ans: print(*l)