(线性DP)
首先考虑路径有交集该如何处理。 可以发现交集中的格子一定在每条路径的相同步数处。因此可以让两个人同时从起点出发,每次同时走一步,这样路径中相交的格子一定在同一步内。
状态表示: 表示两个人同时走了k步,第一个人在 处,第二个人在 处的所有走法的最大分值。
状态计算:按照最后一步两个人的走法分成四种情况:
两个人同时向右走,最大分值是 ; 第一个人向右走,第二个人向下走,最大分值是 ; 第一个人向下走,第二个人向右走,最大分值是 ; 两个人同时向下走,最大分值是 ; 注意两个人不能走到相同格子,即不能相等。
C++代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
int w[N][N];
int f[N+N][N][N];
int n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>w[i][j];
}
}
for(int k=2;k<=m+n;k++){
for(int x1 = max(k-m,1);x1<=min(k-1,n);x1++){
for(int x2 = max(k-m,1);x2<=min(k-1,n);x2++){
int t=w[x1][k-x1];
if(x1!=x2) t+=w[x2][k-x2];
int &x=f[k][x1][x2];
x=max(x,f[k-1][x1-1][x2-1]+t);
x=max(x,f[k-1][x1][x2-1]+t);
x=max(x,f[k-1][x1-1][x2]+t);
x=max(x,f[k-1][x1][x2]+t);
}
}
}
cout<<f[n+m][n][n];
return 0;
}
Go代码
package main
import (
"bufio"
"fmt"
"os"
)
func max(a, b int) int {
if a < b {
return b
}
return a
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
var in = bufio.NewReader(os.Stdin)
const N = 100
var w [N][N]int
var f [N+N][N][N]int
var (
n, m int
)
func main() {
fmt.Fscan(in, &n, &m)
for i := 1; i <= n; i++ {
for j := 1; j <= m; j++ {
fmt.Fscan(in, &w[i][j])
}
}
for k := 2; k <= m+n; k++ {
for x1 := max(k-m, 1); x1 <= min(k-1, n); x1++ {
for x2 := max(k-m, 1); x2 <= min(k-1, n); x2++ {
var t = w[x1][k-x1]
if x1 != x2 {
t += w[x2][k-x2]
}
f[k][x1][x2] = max(f[k][x1][x2], f[k-1][x1-1][x2-1]+t)
f[k][x1][x2] = max(f[k][x1][x2], f[k-1][x1][x2-1]+t)
f[k][x1][x2] = max(f[k][x1][x2], f[k-1][x1-1][x2]+t)
f[k][x1][x2] = max(f[k][x1][x2], f[k-1][x1][x2]+t)
}
}
}
fmt.Println(f[m+n][n][n])
}