Acwing275.传纸条

95 阅读2分钟

275. 传纸条 - AcWing

(线性DP) O(n3)O(n3)O(n3)O(n3)

首先考虑路径有交集该如何处理。 可以发现交集中的格子一定在每条路径的相同步数处。因此可以让两个人同时从起点出发,每次同时走一步,这样路径中相交的格子一定在同一步内。

状态表示:f[k,i,j]f[k, i, j] 表示两个人同时走了k步,第一个人在 (i,ki)(i, k - i) 处,第二个人在 (j,kj)(j, k - j)处的所有走法的最大分值。

状态计算:按照最后一步两个人的走法分成四种情况:

两个人同时向右走,最大分值是 f[k1,i,j]+score(k,i,j)f[k - 1, i, j] + score(k, i, j); 第一个人向右走,第二个人向下走,最大分值是 f[k1,i,j1]+score(k,i,j)f[k - 1, i, j - 1] + score(k, i, j); 第一个人向下走,第二个人向右走,最大分值是 f[k1,i1,j]+score(k,i,j)f[k - 1, i - 1, j] + score(k, i, j); 两个人同时向下走,最大分值是 f[k1,i1,j1]+score(k,i,j)f[k - 1, i - 1, j - 1] + score(k, i, j); 注意两个人不能走到相同格子,即iji和j不能相等。

image.png

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])
}