题目链接:点击这里
把走一次的过程重复两次显然是不行的,局部最优保证不了全局最优!
要求走两次,并且走过的格子,数字就被取走了,且两次走过的格子可能重合,换个思路,假设有两个人同时从左上角出发,到达右下角,这和走两次的情况是等价的!如下图:
假设两个人同时走,一个人在位置 ,另一个人在位置 ,那他们是怎么走过来的呢?显然他们可以从 , , , 这 个组合的位置走到 ,类比数字三角形,我们从那四个位置的组合里选择一个最大的走过来就可以。
注意:和数字三角形所不同的是,当两个人走到同一个格子时,我们需要判断一下坐标,保证当前格子只需一次。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 12;
int a[N][N];
int f[N][N][N][N];
int Max(int a, int b, int c, int d)
{
return max(max(a, b), max(c, d));
}
int main()
{
int n;
scanf("%d", &n);
int r, c, w;
while(~scanf("%d%d%d", &r, &c, &w) && r + c + w) a[r][c] += w;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
for(int ii = 1; ii <= n; ++ii)
{
for(int jj = 1; jj <= n; ++jj)
{
f[i][j][ii][jj] = Max(f[i-1][j][ii-1][jj], f[i][j-1][ii-1][jj], f[i-1][j][ii][jj-1], f[i][j-1][ii][jj-1]);
if(i == ii && j == jj) f[i][j][ii][jj] += a[i][j];
else f[i][j][ii][jj] += a[i][j] + a[ii][jj];
}
}
}
}
printf("%d\n", f[n][n][n][n]);
return 0;
}
yxc代码:在两条路径上的所有格子里,只有当横纵坐标之和相等时才有可能重合,受此启发我们可以将横纵坐标之和当做一维状态,这样可以将状态数量降至3维,且降维后每个状态可以递推出来。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 15;
int n;
int w[N][N];
int f[N*2][N][N];
int Max(int a, int b, int c, int d)
{
return max(max(a, b), max(c, d));
}
int main()
{
scanf("%d", &n);
int a, b, c;
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 >= 1 && j1 <= n && j2 >= 1 && j2 <= n)
{
int &x = f[k][i1][i2];
x = 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]);
if(i1 == i2) x += w[i1][j1];
else x += w[i1][j1] + w[i2][j2];
}
}
}
}
printf("%d\n", f[n+n][n][n]);
return 0;
}