题目大意
小渊坐在矩阵的左上角,坐标 (1,1 ),小轩坐在矩阵的右下角,坐标 (m,n) 。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用 0 表示),可以用一个 0−100 的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这 2 条路径上同学的好心程度之和最大。现在,请你帮助小渊和小轩找到这样的 2 条路径。
思路
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_ROW = 60, MAX_COL = 60, MINF = 0xcfcfcfcf; int A[MAX_ROW][MAX_COL], F[MAX_ROW][MAX_COL][MAX_ROW][MAX_COL]; int TotRow, TotCol; const int Delta[4][4] = { {1,0,1,0}, {1,0,0,1}, {0,1,1,0}, {0,1,0,1} }; int Dfs(int row1, int col1, int row2, int col2) { if (row1 == row2 && col1 == col2 && row1 == TotRow && col1 == TotCol) return 0; if (row1 == row2 && col1 == col2 && (row1 != 1 || row2 != 1 || col1 != 1 || col2 != 1) && (row1 != TotRow || col1 != TotCol)) return MINF; if (row1 > TotRow || col1 > TotCol || row2 > TotRow || col2 > TotCol) return MINF; if (F[row1][col1][row2][col2] != -1) return F[row1][col1][row2][col2]; for (int i = 0; i < 4; i++) F[row1][col1][row2][col2] = max(F[row1][col1][row2][col2], Dfs(row1 + Delta[i][0], col1 + Delta[i][1], row2 + Delta[i][2], col2 + Delta[i][3]) + A[row1][col1] + A[row2][col2]); return F[row1][col1][row2][col2]; } int main() { scanf("%d%d", &TotRow, &TotCol); for (int i = 1; i <= TotRow; i++) for (int j = 1; j <= TotCol; j++) scanf("%d", &A[i][j]); memset(F, -1, sizeof(F)); printf("%d ", Dfs(1, 1, 1, 1)); }