方格取数(数根)

思路:

(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)的最大值;

注意:

  1. 更新时保证(k - i1)在合法范围内。

代码:

#include

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;
}

你可能感兴趣的:(算法)