f[k,i1,i2] : 所有从(1,1),(1,1) 分别到(i1,k - i1) , (i2,k - i2)的最大长度路径
k = i1 + j1 = i2 + j2
状态转移:max(f[k-1][][]) + [重合:w[i1][j1] || 不重合:w[i1][j1] + w[i2][j2] ]
其中max(f[k-1][i1 - 1][i2 -1],f[k-1][i1-1][i2],f[k-1][i1][i2-1],f[k-1][i1][i2]
也就是以下四种转移情况:
第一条:下 下 右 右
第二条:下 右 下 右
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 20;
int n;
int w[N][N];
int f[N*2][N][N];
int main()
{
int a,b,c;
cin>>n;
while(cin>>a>>b>>c,a||b||c) w[a][b] = c;
for(int k = 2; k <= n + n; k ++)
for(int i1 = 1; i1 <= n ; i1 ++)
for(int i2 = 1 ;i2 <= n ; i2 ++)
{
int j1 = k - i1, j2 = k - i2;
//如果存在
if(j1 > 0 && j2 > 0 && j1 <= n && j2 <= n)
{
int t = w[i1][j1]; //重合情况
int &x =f[k][i1][i2];//用x代替表达
if(i1 != i2)t = w[i1][j1] + w[i2][j2]; //不重合情况
x = max(x,f[k-1][i1 - 1][i2 -1] + t);
x = max(x,f[k-1][i1][i2-1] + t);
x = max(x,f[k-1][i1-1][i2] + t);
x = max(x,f[k-1][i1][i2] + t);
}
}
cout << f[n + n][n][n];
return 0;
}