为什么非要用方格取数的办法? 完全可以把两个问题独立思考
与方格取数不同的是, 一个方格只能经过一次
处理方案: 当走到同一个方格时,令$f[k][i1][i2] = -INF$, 则后继状态不会使用这个状态, 就保证了不会走过同一个方格
// AcWing 275. 传纸条, NOIP2008提高组
// 与方格取数不同的是, 一个方格只能经过一次
// 处理方案: 当走到同一个方格时,令f[k][i1][i2] = -INF, 则后继状态不会使用这个状态, 就保证了不会走过同一个方格
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
using namespace std;
const int maxn = 55, INF = 1e9;
int m, n, a[maxn][maxn], f[2 * maxn][maxn][maxn];
int main()
{
cin >> m >> n;
for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) cin >> a[i][j];
for (int k = 2; k <= m + n; k++)
{
for (int i1 = 1; i1 <= m; i1++)
{
for (int i2 = 1; i2 <= m; i2++)
{
int j1 = k - i1, j2 = k - i2;
if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n)
{
if (i1 == i2 && k != 1 && k != m + n) { f[k][i1][i2] = -INF; continue; } // 起点和终点必须都走
int t = a[i1][j1] + a[i2][j2];
int& v = f[k][i1][i2];
v = max(v, f[k - 1][i1 - 1][i2] + t);
v = max(v, f[k - 1][i1 - 1][i2 - 1] + t);
v = max(v, f[k - 1][i1][i2] + t);
v = max(v, f[k - 1][i1][i2 - 1] + t);
}
}
}
}
cout << f[m + n][m][m] << endl;
return 0;
}
注意最后一个是f[n+m][m][m]
搞了我好长时间
就是除了起点和终点只能两次次,其他点都只能走一次
完全不用加特殊判断,直接用方格取数的代码改一下就行,因为那个代码跑出来的两条路径不会重合,满足题意,不需要加特殊判断
k!=2吧虽然没影响hh
能解释下为什么k!= 2没影响吗?所有状态都得从第一个点转移过来啊
起点是(1,1),k = i1 + j1, 所以k != 2
谢谢,不过我的意思是把k!=2删掉为什么也能过,已经想清楚了
为什么走到同一个方格一定比不走到同一个方格大呢,大佬能解答下吗
v = max(v, f[k - 1][i1 - 1][i2] + t);
v = max(v, f[k - 1][i1 - 1][i2 - 1] + t);
v = max(v, f[k - 1][i1][i2] + t);
v = max(v, f[k - 1][i1][i2 - 1] + t);
当走在同一个方格时f[k][i1][i2] = -INF,在最大值判断的时候,另一个值一定是大于-INF的,所以不走同一个方格一定比走同一个方格大,我的理解是这样的
老哥,数据加强了,这个代码过不了了…
诶诶。。。我刚刚测了一个数据点没过,后面又莫名其妙过了!!?
我测了几次, 运行时间34ms, 肯定能过
为啥是两个 m m 啊!写错了?
没有写错呢,可以i1和i2都表示的是行,可以看看大雪莱的代码解释
了解,是我想错了。
这个条件里面的k!=1实际上是没有用到的啊,删掉应该也可以过