思路:将两个人想象为同时走,这样每个状态 i1+j1==i2+j2==k 且可以布满棋盘,因为由k可以推出j1,j2,即每一步的具***置,故状态为f(k,i1,i2) (注:f[k][i1][i2]表示两人经过同样步数,甲在arr[i1]j1, 乙在arr[i2]j2位置时取数的最大值)

下面分析状态的转移计算,有四种情况: 如果到这个步数甲乙没有重合: f(i1,j1,i2,j2)=f(i1-1,j1,i2-1,j2)+arr[i1][j1]+arr[i2][j2] //对应甲从左边来,乙从左边来,下面同理可推 f(i1,j1,i2,j2)=f(i1-1,j1,i2,j2-1)+arr[i1][j1]+arr[i2][j2] f(i1,j1,i2,j2)=f(i1,j1-1,i2-1,j2)+arr[i1][j1]+arr[i2][j2] f(i1,j1,i2,j2)=f(i1,j1-1,i2,j2-1)+arr[i1][j1]+arr[i2][j2] 如果到这个步数甲乙重合: f(i1,j1,i2,j2)=f(i1-1,j1,i2-1,j2)+arr[i1][j1] //甲取走数,该位置的数变为0,对应甲从左边来,乙从左边来,下面同理可推 f(i1,j1,i2,j2)=f(i1-1,j1,i2,j2-1)+arr[i1][j1] f(i1,j1,i2,j2)=f(i1,j1-1,i2-1,j2)+arr[i1][j1] f(i1,j1,i2,j2)=f(i1,j1-1,i2,j2-1)+arr[i1][j1]

优化为3维就是 f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1 - 1][i2 - 1] + t); f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1 - 1][i2] + t); f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1][i2 - 1] + t); f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1][i2] + t);//因为k=i1+j1=i2+j2. i1,i2不变, k-1时, 则对应j1-1, j2-1

最终ac代码如下: #include #include #include

using namespace std;

const int N=15; int arr[N][N]; int f[N + N][N][N];

//将两个人想象为同时走,这样每个状态 i1+j1==i2+j2==k 且可以布满棋盘,因为由k可以推出j1,j2,即每一步的具***置,故状态为f(k,i1,i2) int main() { int r; cin >> r;

int a, b, c;
while (cin >> a >> b >> c&&a || b || c)
{
	arr[a][b] = c;
}
for(int k=2;k<=2*r;k++)
	for(int i1=1;i1<=r;i1++)
		for (int i2 = 1; i2 <= r; i2++)
		{
			int j1 = k - i1, j2 = k - i2;
			if (j1>=1&&j1<=r&&j2>=1&&j2<=r)//注意判断条件
			{
				int t = arr[i1][k - i1];
				if (i1 != i2)t += arr[i2][k - i2];//注意加的逻辑,如果不重合 arr[i1][j1]可能不等于arr[i2][j2],需要加上两个
				f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1 - 1][i2] + t);
				f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1][i2 - 1] + t);
				f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1 - 1][i2 - 1] + t);
				f[k][i1][i2] = max(f[k][i1][i2], f[k - 1][i1][i2] + t);
			}
			
		}
cout << f[r+r][r][r] << endl;

}