思路:
(1)注意到同时走两条路,考虑f[i1][j1][i2][j2]描述第一条路走到(i1,j1)第二条路走到(i2,j2)的最大值;则切分为4种情况,即从左左,左上,上左,上上来四种;若其终点相同,则只加a[i1][j1]即可,否则a[i1][j1],a[i2][j2]都加。
(2)初始化,由于a[i][j] >=0 ,边界值都初始化为0就不会被使用了。
(3)优化:注意到最终要求f[n][n][n][n],所以只用关注i1 + j1 == i2 + j2 的部分即可。
于是用f[k][i1][i2]描述(i1,k - i1),(i2,k - i 2)的最大值;
注意:
- 更新时保证(k - i1)在合法范围内。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 12,INF = -0x3f3f3f3f;
int f[N][N][N][N];
int a[N][N];
int main()
{
int n;
cin >> n;
int x,y,w;
while(cin >> x >> y >> w,x||y||w)
{
a[x][y] = w;
}
for(int k = 2;k <= 2*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 >= 1 && j1 <=n && j2 >=1 && j2 <= n)
{
int t = a[i1][k - i1];
if(i1 != i2) t += a[i2][k - i2];
int &x = f[k][i1][i2];
x = max(f[k - 1][i1 -1][i2 - 1] + t,x );
x = max(f[k - 1][i1][i2 - 1] + t,x );
x = max(f[k - 1][i1 -1][i2] + t,x );
x = max(f[k - 1][i1][i2] + t,x );
}
}
cout << f[2*n][n][n];
// for(int i1 = 1;i1 <= n;i1 ++)
// for(int i2 = 1;i2 <= n;i2 ++)
// for(int j1 = 1;j1 <= n;j1 ++)
// for(int j2 = 1;j2 <= n;j2 ++)
// {
// int t = a[i1][j1];
// if(i1 != i2 || j1 != j2) t += a[i2][j2];
// int &x = f[i1][j1][i2][j2];
// x = max(x,f[i1 - 1][j1][i2 - 1][j2] + t);
// x = max(x,f[i1][j1 - 1][i2 - 1][j2] + t);
// x = max(x,f[i1 - 1][j1][i2][j2 - 1] + t);
// x = max(x,f[i1][j1 - 1][i2 ][j2 - 1] + t);
// }
// cout << f[n][n][n][n];
return 0;
}